diff --git a/app/code/Magento/Bundle/Model/Product/Type.php b/app/code/Magento/Bundle/Model/Product/Type.php
index 4cfdf27fd0e6ab560cf296be35bdb8c5ea8e651e..3e8ae11c4faf362831ead26e549621ea483b9c7c 100644
--- a/app/code/Magento/Bundle/Model/Product/Type.php
+++ b/app/code/Magento/Bundle/Model/Product/Type.php
@@ -546,6 +546,7 @@ class Type extends \Magento\Catalog\Model\Product\Type\AbstractType
             $selectionsCollection = $this->_bundleCollection->create();
             $selectionsCollection->addAttributeToSelect('status');
             $selectionsCollection->addQuantityFilter();
+            $selectionsCollection->setFlag('product_children', true);
             $selectionsCollection->addFilterByRequiredOptions();
             $selectionsCollection->setOptionIdsFilter([$option->getId()]);
 
diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php
index 9f7952e7ae8c882a5b747f9fd24855feea7c380e..10ca7335668470db793498273a998b64e34f4c4f 100644
--- a/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php
+++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php
@@ -8,60 +8,67 @@ namespace Magento\Bundle\Test\Unit\Model\Product;
 use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
 
 /**
+ * Test for Model ProductPrice.
+ *
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
 class PriceTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\CatalogRule\Model\ResourceModel\RuleFactory|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $ruleFactoryMock;
+    private $ruleFactoryMock;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $localeDateMock;
+    private $localeDateMock;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $storeManagerMock;
+    private $storeManagerMock;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $customerSessionMock;
+    private $customerSessionMock;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $eventManagerMock;
+    private $eventManagerMock;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Catalog\Helper\Data|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $catalogHelperMock;
+    private $catalogHelperMock;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Store\Model\Store|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $storeMock;
+    private $storeMock;
 
     /**
      * @var \Magento\Bundle\Model\Product\Price
      */
-    protected $model;
+    private $model;
 
     /**
      * @var \Magento\Framework\Pricing\PriceCurrencyInterface|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $priceCurrency;
+    private $priceCurrency;
 
     /**
-     * @var \Magento\Customer\Api\GroupManagementInterface
+     * @var \Magento\Customer\Api\GroupManagementInterface|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $groupManagement;
+    private $groupManagement;
 
+    /**
+     * Set up.
+     *
+     * @return void
+     */
     protected function setUp()
     {
         $this->ruleFactoryMock = $this->getMock(
@@ -90,6 +97,7 @@ class PriceTest extends \PHPUnit_Framework_TestCase
             false
         );
         $scopeConfig = $this->getMock(\Magento\Framework\App\Config\ScopeConfigInterface::class);
+
         $objectManagerHelper = new ObjectManagerHelper($this);
         $this->model = $objectManagerHelper->getObject(
             \Magento\Bundle\Model\Product\Price::class,
@@ -109,6 +117,8 @@ class PriceTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
+     * Test for calculateSpecialPrice().
+     *
      * @param float $finalPrice
      * @param float $specialPrice
      * @param int $callsNumber
@@ -118,6 +128,7 @@ class PriceTest extends \PHPUnit_Framework_TestCase
      * @covers \Magento\Bundle\Model\Product\Price::calculateSpecialPrice
      * @covers \Magento\Bundle\Model\Product\Price::__construct
      * @dataProvider calculateSpecialPrice
+     * @return void
      */
     public function testCalculateSpecialPrice($finalPrice, $specialPrice, $callsNumber, $dateInInterval, $expected)
     {
@@ -137,6 +148,8 @@ class PriceTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
+     * Data provider for calculateSpecialPrice() test.
+     *
      * @return array
      */
     public function calculateSpecialPrice()
@@ -151,6 +164,11 @@ class PriceTest extends \PHPUnit_Framework_TestCase
         ];
     }
 
+    /**
+     * Test for getTotalBundleItemsPrice() with noCustom options.
+     *
+     * @return void
+     */
     public function testGetTotalBundleItemsPriceWithNoCustomOptions()
     {
         $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
@@ -165,8 +183,11 @@ class PriceTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
+     * Test for getTotalBundleItemsPrice() with empty options.
+     *
      * @param string|null $value
      * @dataProvider dataProviderWithEmptyOptions
+     * @return void
      */
     public function testGetTotalBundleItemsPriceWithEmptyOptions($value)
     {
@@ -194,6 +215,8 @@ class PriceTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
+     * Data provider for getTotalBundleItemsPrice() with empty options.
+     *
      * @return array
      */
     public function dataProviderWithEmptyOptions()
@@ -205,6 +228,11 @@ class PriceTest extends \PHPUnit_Framework_TestCase
         ];
     }
 
+    /**
+     * Test for getTotalBundleItemsPrice() with empty options.
+     *
+     * @return void
+     */
     public function testGetTotalBundleItemsPriceWithNoItems()
     {
         $storeId = 1;
@@ -240,9 +268,8 @@ class PriceTest extends \PHPUnit_Framework_TestCase
             ->method('getStoreId')
             ->willReturn($storeId);
 
-        $dataObjectMock->expects($this->once())
-            ->method('getValue')
-            ->willReturn('a:1:{i:0;s:1:"1";}');
+        $customOptionValue = 'a:1:{i:0;s:1:"1";}';
+        $dataObjectMock->expects($this->once())->method('getValue')->willReturn($customOptionValue);
         $productTypeMock->expects($this->once())
             ->method('getSelectionsByIds')
             ->with([1], $productMock)
diff --git a/app/code/Magento/Catalog/Api/BasePriceStorageInterface.php b/app/code/Magento/Catalog/Api/BasePriceStorageInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..013ec1f940047f1e2c9ce74f95c6f4eb679e04b5
--- /dev/null
+++ b/app/code/Magento/Catalog/Api/BasePriceStorageInterface.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Api;
+
+/**
+ * Base prices storage.
+ * @api
+ */
+interface BasePriceStorageInterface
+{
+    /**
+     * Return product prices.
+     *
+     * @param string[] $skus
+     * @return \Magento\Catalog\Api\Data\BasePriceInterface[]
+     */
+    public function get(array $skus);
+
+    /**
+     * Add or update product prices.
+     *
+     * @param \Magento\Catalog\Api\Data\BasePriceInterface[] $prices
+     * @return bool Will returned True if updated.
+     */
+    public function update(array $prices);
+}
diff --git a/app/code/Magento/Catalog/Api/CostStorageInterface.php b/app/code/Magento/Catalog/Api/CostStorageInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..0c9fb4d540d5bcbe58b92ffb3d1e3794556d39a6
--- /dev/null
+++ b/app/code/Magento/Catalog/Api/CostStorageInterface.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Api;
+
+/**
+ * Product cost storage.
+ * @api
+ */
+interface CostStorageInterface
+{
+    /**
+     * Return product prices.
+     *
+     * @param string[] $skus
+     * @return \Magento\Catalog\Api\Data\CostInterface[]
+     */
+    public function get(array $skus);
+
+    /**
+     * Add or update product cost.
+     *
+     * @param \Magento\Catalog\Api\Data\CostInterface[] $prices
+     * @return bool Will returned True if updated.
+     */
+    public function update(array $prices);
+
+    /**
+     * Delete product cost.
+     *
+     * @param string[] $skus
+     * @return bool Will returned True if deleted.
+     * @throws \Magento\Framework\Exception\CouldNotDeleteException
+     */
+    public function delete(array $skus);
+}
diff --git a/app/code/Magento/Catalog/Api/Data/BasePriceInterface.php b/app/code/Magento/Catalog/Api/Data/BasePriceInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..942de4a63abef74484e7169adbac07c9faa79cdf
--- /dev/null
+++ b/app/code/Magento/Catalog/Api/Data/BasePriceInterface.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Api\Data;
+
+/**
+ * Price interface.
+ * @api
+ */
+interface BasePriceInterface extends \Magento\Framework\Api\ExtensibleDataInterface
+{
+    /**#@+
+     * Constants
+     */
+    const PRICE = 'price';
+    const STORE_ID = 'store_id';
+    const SKU = 'sku';
+    /**#@-*/
+
+    /**
+     * Set price.
+     *
+     * @param float $price
+     * @return $this
+     */
+    public function setPrice($price);
+
+    /**
+     * Get price.
+     *
+     * @return float
+     */
+    public function getPrice();
+
+    /**
+     * Set store id.
+     *
+     * @param int $storeId
+     * @return $this
+     */
+    public function setStoreId($storeId);
+
+    /**
+     * Get store id.
+     *
+     * @return int
+     */
+    public function getStoreId();
+
+    /**
+     * Set SKU.
+     *
+     * @param string $sku
+     * @return $this
+     */
+    public function setSku($sku);
+
+    /**
+     * Get SKU.
+     *
+     * @return string
+     */
+    public function getSku();
+
+    /**
+     * Retrieve existing extension attributes object or create a new one.
+     *
+     * @return \Magento\Catalog\Api\Data\BasePriceExtensionInterface|null
+     */
+    public function getExtensionAttributes();
+
+    /**
+     * Set an extension attributes object.
+     *
+     * @param \Magento\Catalog\Api\Data\BasePriceExtensionInterface $extensionAttributes
+     * @return $this
+     */
+    public function setExtensionAttributes(
+        \Magento\Catalog\Api\Data\BasePriceExtensionInterface $extensionAttributes
+    );
+}
diff --git a/app/code/Magento/Catalog/Api/Data/CostInterface.php b/app/code/Magento/Catalog/Api/Data/CostInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..c007c81f1d7bf9181215044701b18205322be49b
--- /dev/null
+++ b/app/code/Magento/Catalog/Api/Data/CostInterface.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Api\Data;
+
+/**
+ * Cost interface.
+ * @api
+ */
+interface CostInterface extends \Magento\Framework\Api\ExtensibleDataInterface
+{
+    /**#@+
+     * Constants
+     */
+    const COST = 'cost';
+    const STORE_ID = 'store_id';
+    const SKU = 'sku';
+    /**#@-*/
+
+    /**
+     * Set cost value.
+     *
+     * @param float $cost
+     * @return $this
+     */
+    public function setCost($cost);
+
+    /**
+     * Get cost value.
+     *
+     * @return float
+     */
+    public function getCost();
+
+    /**
+     * Set store id.
+     *
+     * @param int $storeId
+     * @return $this
+     */
+    public function setStoreId($storeId);
+
+    /**
+     * Get store id.
+     *
+     * @return int
+     */
+    public function getStoreId();
+
+    /**
+     * Set SKU.
+     *
+     * @param string $sku
+     * @return $this
+     */
+    public function setSku($sku);
+
+    /**
+     * Get SKU.
+     *
+     * @return string
+     */
+    public function getSku();
+
+    /**
+     * Retrieve existing extension attributes object or create a new one.
+     *
+     * @return \Magento\Catalog\Api\Data\CostExtensionInterface|null
+     */
+    public function getExtensionAttributes();
+
+    /**
+     * Set an extension attributes object.
+     *
+     * @param \Magento\Catalog\Api\Data\CostExtensionInterface $extensionAttributes
+     * @return $this
+     */
+    public function setExtensionAttributes(
+        \Magento\Catalog\Api\Data\CostExtensionInterface $extensionAttributes
+    );
+}
diff --git a/app/code/Magento/Catalog/Api/Data/TierPriceInterface.php b/app/code/Magento/Catalog/Api/Data/TierPriceInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..1b708132c0d0ef95f900690e53b6520dac2fa008
--- /dev/null
+++ b/app/code/Magento/Catalog/Api/Data/TierPriceInterface.php
@@ -0,0 +1,134 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Api\Data;
+
+/**
+ * Tier price interface.
+ * @api
+ */
+interface TierPriceInterface extends \Magento\Framework\Api\ExtensibleDataInterface
+{
+    /**#@+
+     * Constants
+     */
+    const PRICE = 'price';
+    const PRICE_TYPE = 'price_type';
+    const WEBSITE_ID = 'website_id';
+    const SKU = 'sku';
+    const CUSTOMER_GROUP = 'customer_group';
+    const QUANTITY = 'quantity';
+    const PRICE_TYPE_FIXED = 'fixed';
+    const PRICE_TYPE_DISCOUNT = 'discount';
+    /**#@-*/
+
+    /**
+     * Set tier price.
+     *
+     * @param float $price
+     * @return $this
+     */
+    public function setPrice($price);
+
+    /**
+     * Get tier price.
+     *
+     * @return float
+     */
+    public function getPrice();
+
+    /**
+     * Set tier price type.
+     *
+     * @param string $type
+     * @return $this
+     */
+    public function setPriceType($type);
+
+    /**
+     * Get tier price type.
+     *
+     * @return string
+     */
+    public function getPriceType();
+
+    /**
+     * Set website id.
+     *
+     * @param int $websiteId
+     * @return $this
+     */
+    public function setWebsiteId($websiteId);
+
+    /**
+     * Get website id.
+     *
+     * @return int
+     */
+    public function getWebsiteId();
+
+    /**
+     * Set SKU.
+     *
+     * @param string $sku
+     * @return $this
+     */
+    public function setSku($sku);
+
+    /**
+     * Get SKU.
+     *
+     * @return string
+     */
+    public function getSku();
+
+    /**
+     * Set customer group.
+     *
+     * @param string $group
+     * @return $this
+     */
+    public function setCustomerGroup($group);
+
+    /**
+     * Get customer group.
+     *
+     * @return string
+     */
+    public function getCustomerGroup();
+
+    /**
+     * Set quantity.
+     *
+     * @param float $quantity
+     * @return $this
+     */
+    public function setQuantity($quantity);
+
+    /**
+     * Get quantity.
+     *
+     * @return float
+     */
+    public function getQuantity();
+
+    /**
+     * Retrieve existing extension attributes object or create a new one.
+     *
+     * @return \Magento\Catalog\Api\Data\TierPriceExtensionInterface|null
+     */
+    public function getExtensionAttributes();
+
+    /**
+     * Set an extension attributes object.
+     *
+     * @param \Magento\Catalog\Api\Data\TierPriceExtensionInterface $extensionAttributes
+     * @return $this
+     */
+    public function setExtensionAttributes(
+        \Magento\Catalog\Api\Data\TierPriceExtensionInterface $extensionAttributes
+    );
+}
diff --git a/app/code/Magento/Catalog/Api/TierPriceStorageInterface.php b/app/code/Magento/Catalog/Api/TierPriceStorageInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..200cdc1baa411c0ec63b9161f5829c1b29724315
--- /dev/null
+++ b/app/code/Magento/Catalog/Api/TierPriceStorageInterface.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Api;
+
+/**
+ * Tier prices storage.
+ * @api
+ */
+interface TierPriceStorageInterface
+{
+    /**
+     * Return product prices.
+     *
+     * @param string[] $skus
+     * @return \Magento\Catalog\Api\Data\TierPriceInterface[]
+     */
+    public function get(array $skus);
+
+    /**
+     * Add or update product prices.
+     *
+     * @param \Magento\Catalog\Api\Data\TierPriceInterface[] $prices
+     * @return bool Will returned True if updated.
+     */
+    public function update(array $prices);
+
+    /**
+     * Remove existing tier prices and replace them with the new ones.
+     *
+     * @param \Magento\Catalog\Api\Data\TierPriceInterface[] $prices
+     * @return bool Will returned True if replaced.
+     */
+    public function replace(array $prices);
+
+    /**
+     * Delete product tier prices.
+     *
+     * @param \Magento\Catalog\Api\Data\TierPriceInterface[] $prices
+     * @return bool Will returned True if deleted.
+     */
+    public function delete(array $prices);
+}
diff --git a/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php b/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php
index 5e518df37db1a574f25fe008510e75742cdffa9c..b994c787bee7aa76f8a4baa3648bcbb2c0e4ee27 100644
--- a/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php
+++ b/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php
@@ -23,7 +23,7 @@ class Price implements ProductPriceOptionsInterface
     {
         return [
             ['value' => self::VALUE_FIXED, 'label' => __('Fixed')],
-            ['value' => self::VALUE_PERCENT, 'label' => __('Discount')],
+            ['value' => self::VALUE_PERCENT, 'label' => __('Percent')],
         ];
     }
 }
diff --git a/app/code/Magento/Catalog/Model/Config/Source/Product/Options/TierPrice.php b/app/code/Magento/Catalog/Model/Config/Source/Product/Options/TierPrice.php
new file mode 100644
index 0000000000000000000000000000000000000000..d630f4890fc95afd894ab88b81aedc552e9bc50c
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Config/Source/Product/Options/TierPrice.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Catalog\Model\Config\Source\Product\Options;
+
+use Magento\Catalog\Model\Config\Source\ProductPriceOptionsInterface;
+
+/**
+ * TierPrice types mode source.
+ */
+class TierPrice implements ProductPriceOptionsInterface
+{
+    /**
+     * {@inheritdoc}
+     *
+     * @codeCoverageIgnore
+     */
+    public function toOptionArray()
+    {
+        return [
+            ['value' => self::VALUE_FIXED, 'label' => __('Fixed')],
+            ['value' => self::VALUE_PERCENT, 'label' => __('Discount')],
+        ];
+    }
+}
diff --git a/app/code/Magento/Catalog/Model/Product/Price/BasePrice.php b/app/code/Magento/Catalog/Model/Product/Price/BasePrice.php
new file mode 100644
index 0000000000000000000000000000000000000000..b7c01141de33bb7202ccad4eff2605bb7bdcbae8
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Product/Price/BasePrice.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Model\Product\Price;
+
+use Magento\Catalog\Api\Data\BasePriceInterface;
+
+/**
+ * Product Base Price DTO.
+ */
+class BasePrice extends \Magento\Framework\Model\AbstractExtensibleModel implements BasePriceInterface
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function setPrice($price)
+    {
+        return $this->setData(self::PRICE, $price);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getPrice()
+    {
+        return $this->getData(self::PRICE);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setStoreId($storeId)
+    {
+        return $this->setData(self::STORE_ID, $storeId);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getStoreId()
+    {
+        return $this->getData(self::STORE_ID);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setSku($sku)
+    {
+        return $this->setData(self::SKU, $sku);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getSku()
+    {
+        return $this->getData(self::SKU);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getExtensionAttributes()
+    {
+        return $this->_getExtensionAttributes();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setExtensionAttributes(\Magento\Catalog\Api\Data\BasePriceExtensionInterface $extensionAttributes)
+    {
+        return $this->_setExtensionAttributes($extensionAttributes);
+    }
+}
diff --git a/app/code/Magento/Catalog/Model/Product/Price/BasePriceStorage.php b/app/code/Magento/Catalog/Model/Product/Price/BasePriceStorage.php
new file mode 100644
index 0000000000000000000000000000000000000000..e69f89f0bb146d62e7cc65d1022a4d25b6738c4f
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Product/Price/BasePriceStorage.php
@@ -0,0 +1,227 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Model\Product\Price;
+
+/**
+ * Base prices storage.
+ */
+class BasePriceStorage implements \Magento\Catalog\Api\BasePriceStorageInterface
+{
+    /**
+     * Attribute code.
+     *
+     * @var string
+     */
+    private $attributeCode = 'price';
+
+    /**
+     * @var PricePersistence
+     */
+    private $pricePersistence;
+
+    /**
+     * @var \Magento\Catalog\Api\Data\BasePriceInterfaceFactory
+     */
+    private $basePriceInterfaceFactory;
+
+    /**
+     * @var \Magento\Catalog\Model\ProductIdLocatorInterface
+     */
+    private $productIdLocator;
+
+    /**
+     * @var \Magento\Store\Api\StoreRepositoryInterface
+     */
+    private $storeRepository;
+
+    /**
+     * @var \Magento\Catalog\Api\ProductRepositoryInterface
+     */
+    private $productRepository;
+
+    /**
+     * Price type allowed.
+     *
+     * @var int
+     */
+    private $priceTypeAllowed = 1;
+
+    /**
+     * Allowed product types.
+     *
+     * @var array
+     */
+    private $allowedProductTypes = [];
+
+    /**
+     * @var PricePersistenceFactory
+     */
+    private $pricePersistenceFactory;
+
+    /**
+     * BasePriceStorage constructor.
+     *
+     * @param PricePersistenceFactory $pricePersistenceFactory
+     * @param \Magento\Catalog\Api\Data\BasePriceInterfaceFactory $basePriceInterfaceFactory
+     * @param \Magento\Catalog\Model\ProductIdLocatorInterface $productIdLocator
+     * @param \Magento\Store\Api\StoreRepositoryInterface $storeRepository
+     * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
+     * @param array $allowedProductTypes
+     */
+    public function __construct(
+        PricePersistenceFactory $pricePersistenceFactory,
+        \Magento\Catalog\Api\Data\BasePriceInterfaceFactory $basePriceInterfaceFactory,
+        \Magento\Catalog\Model\ProductIdLocatorInterface $productIdLocator,
+        \Magento\Store\Api\StoreRepositoryInterface $storeRepository,
+        \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
+        array $allowedProductTypes = []
+    ) {
+        $this->pricePersistenceFactory = $pricePersistenceFactory;
+        $this->basePriceInterfaceFactory = $basePriceInterfaceFactory;
+        $this->productIdLocator = $productIdLocator;
+        $this->storeRepository = $storeRepository;
+        $this->productRepository = $productRepository;
+        $this->allowedProductTypes = $allowedProductTypes;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function get(array $skus)
+    {
+        $this->validateSkus($skus);
+        $rawPrices = $this->getPricePersistence()->get($skus);
+        $prices = [];
+        foreach ($rawPrices as $rawPrice) {
+            $price = $this->basePriceInterfaceFactory->create();
+            $sku = $this->getPricePersistence()
+                ->retrieveSkuById($rawPrice[$this->getPricePersistence()->getEntityLinkField()], $skus);
+            $price->setSku($sku);
+            $price->setPrice($rawPrice['value']);
+            $price->setStoreId($rawPrice['store_id']);
+            $prices[] = $price;
+        }
+
+        return $prices;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function update(array $prices)
+    {
+        $this->validate($prices);
+        $formattedPrices = [];
+
+        foreach ($prices as $price) {
+            $ids = array_keys($this->productIdLocator->retrieveProductIdsBySkus([$price->getSku()])[$price->getSku()]);
+            foreach ($ids as $id) {
+                $formattedPrices[] = [
+                    'store_id' => $price->getStoreId(),
+                    $this->getPricePersistence()->getEntityLinkField() => $id,
+                    'value' => $price->getPrice(),
+                ];
+            }
+        }
+
+        $this->getPricePersistence()->update($formattedPrices);
+
+        return true;
+    }
+
+    /**
+     * Get price persistence.
+     *
+     * @return PricePersistence
+     */
+    private function getPricePersistence()
+    {
+        if (!$this->pricePersistence) {
+            $this->pricePersistence = $this->pricePersistenceFactory->create(['attributeCode' => $this->attributeCode]);
+        }
+
+        return $this->pricePersistence;
+    }
+
+    /**
+     * Validate SKU, check product types and skip not existing products.
+     *
+     * @param array $skus
+     * @throws \Magento\Framework\Exception\LocalizedException
+     * @return void
+     */
+    private function validateSkus(array $skus)
+    {
+        $idsBySku = $this->productIdLocator->retrieveProductIdsBySkus($skus);
+        $skuDiff = array_diff($skus, array_keys($idsBySku));
+
+        foreach ($idsBySku as $sku => $ids) {
+            foreach ($ids as $type) {
+                if (!in_array($type, $this->allowedProductTypes)
+                    || (
+                        $type == \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE
+                        && $this->productRepository->get($sku)->getPriceType() != $this->priceTypeAllowed
+                    )
+                ) {
+                    $skuDiff[] = $sku;
+                    break;
+                }
+            }
+        }
+
+        if (!empty($skuDiff)) {
+            $values = implode(', ', $skuDiff);
+            $description = count($skuDiff) == 1
+                ? __('Requested product doesn\'t exist: %1', $values)
+                : __('Requested products don\'t exist: %1', $values);
+            throw new \Magento\Framework\Exception\NoSuchEntityException($description);
+        }
+    }
+
+    /**
+     * Validate that prices have appropriate values.
+     *
+     * @param array $prices
+     * @throws \Magento\Framework\Exception\LocalizedException
+     * @return void
+     */
+    private function validate(array $prices)
+    {
+        $skus = array_unique(
+            array_map(function ($price) {
+                if (!$price->getSku()) {
+                    throw new \Magento\Framework\Exception\LocalizedException(
+                        __(
+                            'Invalid attribute %fieldName: %fieldValue.',
+                            [
+                                'fieldName' => 'sku',
+                                'fieldValue' => $price->getSku()
+                            ]
+                        )
+                    );
+                }
+                return $price->getSku();
+            }, $prices)
+        );
+        $this->validateSkus($skus);
+
+        foreach ($prices as $price) {
+            if (null === $price->getPrice() || $price->getPrice() < 0) {
+                throw new \Magento\Framework\Exception\LocalizedException(
+                    __(
+                        'Invalid attribute %fieldName: %fieldValue.',
+                        [
+                            'fieldName' => 'Price',
+                            'fieldValue' => $price->getPrice()
+                        ]
+                    )
+                );
+            }
+            $this->storeRepository->getById($price->getStoreId());
+        }
+    }
+}
diff --git a/app/code/Magento/Catalog/Model/Product/Price/Cost.php b/app/code/Magento/Catalog/Model/Product/Price/Cost.php
new file mode 100644
index 0000000000000000000000000000000000000000..8d52c578ea94b431254883d0e815c1f0064c22d2
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Product/Price/Cost.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Model\Product\Price;
+
+use Magento\Catalog\Api\Data\CostInterface;
+
+/**
+ * Product Cost DTO.
+ */
+class Cost extends \Magento\Framework\Model\AbstractExtensibleModel implements CostInterface
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function setCost($cost)
+    {
+        return $this->setData(self::COST, $cost);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getCost()
+    {
+        return $this->getData(self::COST);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setStoreId($storeId)
+    {
+        return $this->setData(self::STORE_ID, $storeId);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getStoreId()
+    {
+        return $this->getData(self::STORE_ID);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setSku($sku)
+    {
+        return $this->setData(self::SKU, $sku);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getSku()
+    {
+        return $this->getData(self::SKU);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getExtensionAttributes()
+    {
+        return $this->_getExtensionAttributes();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setExtensionAttributes(\Magento\Catalog\Api\Data\CostExtensionInterface $extensionAttributes)
+    {
+        return $this->_setExtensionAttributes($extensionAttributes);
+    }
+}
diff --git a/app/code/Magento/Catalog/Model/Product/Price/CostStorage.php b/app/code/Magento/Catalog/Model/Product/Price/CostStorage.php
new file mode 100644
index 0000000000000000000000000000000000000000..e7fc682514a3fa3c575f13938a0a86048a0e50fb
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Product/Price/CostStorage.php
@@ -0,0 +1,218 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Model\Product\Price;
+
+/**
+ * Product cost storage.
+ */
+class CostStorage implements \Magento\Catalog\Api\CostStorageInterface
+{
+    /**
+     * Attribute code.
+     *
+     * @var string
+     */
+    private $attributeCode = 'cost';
+
+    /**
+     * @var PricePersistence
+     */
+    private $pricePersistence;
+
+    /**
+     * @var \Magento\Catalog\Api\Data\CostInterfaceFactory
+     */
+    private $costInterfaceFactory;
+
+    /**
+     * @var \Magento\Catalog\Model\ProductIdLocatorInterface
+     */
+    private $productIdLocator;
+
+    /**
+     * Allowed product types.
+     *
+     * @var array
+     */
+    private $allowedProductTypes = [];
+
+    /**
+     * @var PricePersistenceFactory
+     */
+    private $pricePersistenceFactory;
+
+    /**
+     * @var \Magento\Store\Api\StoreRepositoryInterface
+     */
+    private $storeRepository;
+
+    /**
+     * CostStorage constructor.
+     *
+     * @param PricePersistenceFactory $pricePersistenceFactory
+     * @param \Magento\Catalog\Api\Data\CostInterfaceFactory $costInterfaceFactory
+     * @param \Magento\Catalog\Model\ProductIdLocatorInterface $productIdLocator
+     * @param \Magento\Store\Api\StoreRepositoryInterface $storeRepository
+     * @param array $allowedProductTypes
+     */
+    public function __construct(
+        PricePersistenceFactory $pricePersistenceFactory,
+        \Magento\Catalog\Api\Data\CostInterfaceFactory $costInterfaceFactory,
+        \Magento\Catalog\Model\ProductIdLocatorInterface $productIdLocator,
+        \Magento\Store\Api\StoreRepositoryInterface $storeRepository,
+        array $allowedProductTypes = []
+    ) {
+        $this->pricePersistenceFactory = $pricePersistenceFactory;
+        $this->costInterfaceFactory = $costInterfaceFactory;
+        $this->productIdLocator = $productIdLocator;
+        $this->storeRepository = $storeRepository;
+        $this->allowedProductTypes = $allowedProductTypes;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function get(array $skus)
+    {
+        $this->validateSkus($skus);
+        $rawPrices = $this->getPricePersistence()->get($skus);
+        $prices = [];
+        foreach ($rawPrices as $rawPrice) {
+            $price = $this->costInterfaceFactory->create();
+            $sku = $this->getPricePersistence()
+                ->retrieveSkuById($rawPrice[$this->getPricePersistence()->getEntityLinkField()], $skus);
+            $price->setSku($sku);
+            $price->setCost($rawPrice['value']);
+            $price->setStoreId($rawPrice['store_id']);
+            $prices[] = $price;
+        }
+
+        return $prices;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function update(array $prices)
+    {
+        $this->validate($prices);
+        $formattedPrices = [];
+
+        foreach ($prices as $price) {
+            $ids = array_keys($this->productIdLocator->retrieveProductIdsBySkus([$price->getSku()])[$price->getSku()]);
+            foreach ($ids as $id) {
+                $formattedPrices[] = [
+                    'store_id' => $price->getStoreId(),
+                    $this->getPricePersistence()->getEntityLinkField() => $id,
+                    'value' => $price->getCost(),
+                ];
+            }
+        }
+
+        $this->getPricePersistence()->update($formattedPrices);
+
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function delete(array $skus)
+    {
+        $this->validateSkus($skus);
+        $this->getPricePersistence()->delete($skus);
+
+        return true;
+    }
+
+    /**
+     * Get price persistence.
+     *
+     * @return PricePersistence
+     */
+    private function getPricePersistence()
+    {
+        if (!$this->pricePersistence) {
+            $this->pricePersistence = $this->pricePersistenceFactory->create(['attributeCode' => $this->attributeCode]);
+        }
+
+        return $this->pricePersistence;
+    }
+
+    /**
+     * Validate that prices have appropriate values.
+     *
+     * @param array $prices
+     * @throws \Magento\Framework\Exception\LocalizedException
+     * @return void
+     */
+    private function validate(array $prices)
+    {
+        $skus = array_unique(
+            array_map(function ($price) {
+                if (!$price->getSku()) {
+                    throw new \Magento\Framework\Exception\LocalizedException(
+                        __(
+                            'Invalid attribute %fieldName: %fieldValue.',
+                            [
+                                'fieldName' => 'sku',
+                                'fieldValue' => $price->getSku()
+                            ]
+                        )
+                    );
+                }
+                return $price->getSku();
+            }, $prices)
+        );
+        $this->validateSkus($skus);
+
+        foreach ($prices as $price) {
+            if (null === $price->getCost() || $price->getCost() < 0) {
+                throw new \Magento\Framework\Exception\LocalizedException(
+                    __(
+                        'Invalid attribute %fieldName: %fieldValue.',
+                        [
+                            'fieldName' => 'Cost',
+                            'fieldValue' => $price->getCost()
+                        ]
+                    )
+                );
+            }
+            $this->storeRepository->getById($price->getStoreId());
+        }
+    }
+
+    /**
+     * Validate SKU, check product types and skip not existing products.
+     *
+     * @param array $skus
+     * @throws \Magento\Framework\Exception\LocalizedException
+     * @return void
+     */
+    private function validateSkus(array $skus)
+    {
+        $idsBySku = $this->productIdLocator->retrieveProductIdsBySkus($skus);
+        $skuDiff = array_diff($skus, array_keys($idsBySku));
+
+        foreach ($idsBySku as $sku => $ids) {
+            foreach (array_values($ids) as $type) {
+                if (!in_array($type, $this->allowedProductTypes)) {
+                    $skuDiff[] = $sku;
+                    break;
+                }
+            }
+        }
+
+        if (!empty($skuDiff)) {
+            $values = implode(', ', $skuDiff);
+            $description = count($skuDiff) == 1
+                ? __('Requested product doesn\'t exist: %1', $values)
+                : __('Requested products don\'t exist: %1', $values);
+            throw new \Magento\Framework\Exception\NoSuchEntityException($description);
+        }
+    }
+}
diff --git a/app/code/Magento/Catalog/Model/Product/Price/PricePersistence.php b/app/code/Magento/Catalog/Model/Product/Price/PricePersistence.php
new file mode 100644
index 0000000000000000000000000000000000000000..f37fb15cd47e433e4125b0bd51d90d00ae291cf2
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Product/Price/PricePersistence.php
@@ -0,0 +1,228 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Model\Product\Price;
+
+/**
+ * Price persistence.
+ */
+class PricePersistence
+{
+    /**
+     * Price storage table.
+     *
+     * @var string
+     */
+    private $table = 'catalog_product_entity_decimal';
+
+    /**
+     * @var \Magento\Catalog\Model\ResourceModel\Attribute
+     */
+    private $attributeResource;
+
+    /**
+     * @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface
+     */
+    private $attributeRepository;
+
+    /**
+     * @var \Magento\Catalog\Model\ProductIdLocatorInterface
+     */
+    private $productIdLocator;
+
+    /**
+     * Metadata pool.
+     *
+     * @var \Magento\Framework\EntityManager\MetadataPool
+     */
+    private $metadataPool;
+
+    /**
+     * Attribute code.
+     *
+     * @var string
+     */
+    private $attributeCode;
+
+    /**
+     * Attribute ID.
+     *
+     * @var int
+     */
+    private $attributeId;
+
+    /**
+     * Items per operation.
+     *
+     * @var int
+     */
+    private $itemsPerOperation = 500;
+
+    /**
+     * PricePersistence constructor.
+     *
+     * @param \Magento\Catalog\Model\ResourceModel\Attribute $attributeResource
+     * @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository
+     * @param \Magento\Catalog\Model\ProductIdLocatorInterface $productIdLocator
+     * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool
+     * @param string $attributeCode
+     */
+    public function __construct(
+        \Magento\Catalog\Model\ResourceModel\Attribute $attributeResource,
+        \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository,
+        \Magento\Catalog\Model\ProductIdLocatorInterface $productIdLocator,
+        \Magento\Framework\EntityManager\MetadataPool $metadataPool,
+        $attributeCode = ''
+    ) {
+        $this->attributeResource = $attributeResource;
+        $this->attributeRepository = $attributeRepository;
+        $this->attributeCode = $attributeCode;
+        $this->productIdLocator = $productIdLocator;
+        $this->metadataPool = $metadataPool;
+    }
+
+    /**
+     * Get prices by SKUs.
+     *
+     * @param array $skus
+     * @return array
+     */
+    public function get(array $skus)
+    {
+        $ids = $this->retrieveAffectedIds($skus);
+        $select = $this->attributeResource->getConnection()
+            ->select()
+            ->from($this->attributeResource->getTable($this->table));
+        return $this->attributeResource->getConnection()->fetchAll(
+            $select->where($this->getEntityLinkField() . ' IN (?)', $ids)
+                ->where('attribute_id = ?', $this->getAttributeId())
+        );
+    }
+
+    /**
+     * Update prices.
+     *
+     * @param array $prices
+     * @return void
+     * @throws \Magento\Framework\Exception\CouldNotSaveException
+     */
+    public function update(array $prices)
+    {
+        array_walk($prices, function (&$price) {
+            return $price['attribute_id'] = $this->getAttributeId();
+        });
+        $connection = $this->attributeResource->getConnection();
+        $connection->beginTransaction();
+        try {
+            foreach (array_chunk($prices, $this->itemsPerOperation) as $pricesBunch) {
+                $this->attributeResource->getConnection()->insertOnDuplicate(
+                    $this->attributeResource->getTable($this->table),
+                    $pricesBunch,
+                    ['value']
+                );
+            }
+            $connection->commit();
+        } catch (\Exception $e) {
+            $connection->rollBack();
+            throw new \Magento\Framework\Exception\CouldNotSaveException(
+                __('Could not save Prices.'),
+                $e
+            );
+        }
+    }
+
+    /**
+     * Delete product attribute by SKU.
+     *
+     * @param array $skus
+     * @return void
+     * @throws \Magento\Framework\Exception\CouldNotDeleteException
+     */
+    public function delete(array $skus)
+    {
+        $ids = $this->retrieveAffectedIds($skus);
+        $connection = $this->attributeResource->getConnection();
+        $connection->beginTransaction();
+        try {
+            foreach (array_chunk($ids, $this->itemsPerOperation) as $idsBunch) {
+                $this->attributeResource->getConnection()->delete(
+                    $this->attributeResource->getTable($this->table),
+                    [
+                        'attribute_id = ?' => $this->getAttributeId(),
+                        $this->getEntityLinkField() . ' IN (?)' => $idsBunch
+                    ]
+                );
+            }
+            $connection->commit();
+        } catch (\Exception $e) {
+            $connection->rollBack();
+            throw new \Magento\Framework\Exception\CouldNotDeleteException(
+                __('Could not delete Prices'),
+                $e
+            );
+        }
+    }
+
+    /**
+     * Retrieve SKU by product ID.
+     *
+     * @param int $id
+     * @param array $skus
+     * @return int|null
+     */
+    public function retrieveSkuById($id, $skus)
+    {
+        foreach ($this->productIdLocator->retrieveProductIdsBySkus($skus) as $sku => $ids) {
+            if (false !== array_key_exists($id, $ids)) {
+                return $sku;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Get attribute ID.
+     *
+     * @return int
+     */
+    private function getAttributeId()
+    {
+        if (!$this->attributeId) {
+            $this->attributeId = $this->attributeRepository->get($this->attributeCode)->getAttributeId();
+        }
+
+        return $this->attributeId;
+    }
+
+    /**
+     * Retrieve affected product IDs.
+     *
+     * @param array $skus
+     * @return array
+     */
+    private function retrieveAffectedIds(array $skus)
+    {
+        $affectedIds = [];
+
+        foreach ($this->productIdLocator->retrieveProductIdsBySkus($skus) as $productIds) {
+            $affectedIds = array_merge($affectedIds, array_keys($productIds));
+        }
+
+        return array_unique($affectedIds);
+    }
+
+    /**
+     * Get link field.
+     *
+     * @return string
+     */
+    public function getEntityLinkField()
+    {
+        return $this->metadataPool->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class)
+            ->getLinkField();
+    }
+}
diff --git a/app/code/Magento/Catalog/Model/Product/Price/TierPrice.php b/app/code/Magento/Catalog/Model/Product/Price/TierPrice.php
new file mode 100644
index 0000000000000000000000000000000000000000..c3c30d18fe639df371a6a5b3d51f7f06492be4f5
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Product/Price/TierPrice.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Model\Product\Price;
+
+use Magento\Catalog\Api\Data\TierPriceInterface;
+
+/**
+ * TierPrice DTO.
+ */
+class TierPrice extends \Magento\Framework\Model\AbstractExtensibleModel implements TierPriceInterface
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function setPrice($price)
+    {
+        return $this->setData(self::PRICE, $price);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getPrice()
+    {
+        return $this->getData(self::PRICE);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setPriceType($type)
+    {
+        return $this->setData(self::PRICE_TYPE, $type);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getPriceType()
+    {
+        return $this->getData(self::PRICE_TYPE);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setWebsiteId($websiteId)
+    {
+        return $this->setData(self::WEBSITE_ID, $websiteId);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getWebsiteId()
+    {
+        return $this->getData(self::WEBSITE_ID);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setSku($sku)
+    {
+        return $this->setData(self::SKU, $sku);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getSku()
+    {
+        return $this->getData(self::SKU);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setCustomerGroup($group)
+    {
+        return $this->setData(self::CUSTOMER_GROUP, $group);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getCustomerGroup()
+    {
+        return $this->getData(self::CUSTOMER_GROUP);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setQuantity($quantity)
+    {
+        return $this->setData(self::QUANTITY, $quantity);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getQuantity()
+    {
+        return $this->getData(self::QUANTITY);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getExtensionAttributes()
+    {
+        return $this->_getExtensionAttributes();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setExtensionAttributes(\Magento\Catalog\Api\Data\TierPriceExtensionInterface $extensionAttributes)
+    {
+        return $this->_setExtensionAttributes($extensionAttributes);
+    }
+}
diff --git a/app/code/Magento/Catalog/Model/Product/Price/TierPriceFactory.php b/app/code/Magento/Catalog/Model/Product/Price/TierPriceFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..1e031649ebdcf2830826e57dccb974a51b7efa71
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Product/Price/TierPriceFactory.php
@@ -0,0 +1,169 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Model\Product\Price;
+
+use Magento\Catalog\Api\Data\TierPriceInterface;
+use Magento\Framework\Exception\NoSuchEntityException;
+
+/**
+ * Tier price factory.
+ */
+class TierPriceFactory
+{
+    /**
+     * Tier price factory.
+     *
+     * @var \Magento\Catalog\Api\Data\TierPriceInterfaceFactory
+     */
+    private $tierPriceFactory;
+
+    /**
+     * Tier price persistence.
+     *
+     * @var TierPricePersistence
+     */
+    private $tierPricePersistence;
+
+    /**
+     * Customer group repository.
+     *
+     * @var \Magento\Customer\Api\GroupRepositoryInterface
+     */
+    private $customerGroupRepository;
+
+    /**
+     * All groups value.
+     *
+     * @var string
+     */
+    private $allGroupsValue = 'all groups';
+
+    /**
+     * All groups ID.
+     *
+     * @var int
+     */
+    private $allGroupsId = 1;
+
+    /**
+     * Customer groups by code.
+     *
+     * @var array
+     */
+    private $customerGroupsByCode = [];
+
+    /**
+     * TierPriceBuilder constructor.
+     *
+     * @param \Magento\Catalog\Api\Data\TierPriceInterfaceFactory $tierPriceFactory
+     * @param TierPricePersistence $tierPricePersistence
+     * @param \Magento\Customer\Api\GroupRepositoryInterface $customerGroupRepository
+     * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
+     * @param \Magento\Framework\Api\FilterBuilder $filterBuilder
+     */
+    public function __construct(
+        \Magento\Catalog\Api\Data\TierPriceInterfaceFactory $tierPriceFactory,
+        TierPricePersistence $tierPricePersistence,
+        \Magento\Customer\Api\GroupRepositoryInterface $customerGroupRepository,
+        \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
+        \Magento\Framework\Api\FilterBuilder $filterBuilder
+    ) {
+        $this->tierPriceFactory = $tierPriceFactory;
+        $this->tierPricePersistence = $tierPricePersistence;
+        $this->customerGroupRepository = $customerGroupRepository;
+        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
+        $this->filterBuilder = $filterBuilder;
+    }
+
+    /**
+     * Create populated tier price DTO.
+     *
+     * @param array $rawPrice
+     * @param string $sku
+     * @return \Magento\Catalog\Api\Data\TierPriceInterface
+     */
+    public function create(array $rawPrice, $sku)
+    {
+        $price = $this->tierPriceFactory->create();
+        $price->setPrice(isset($rawPrice['percentage_value']) ? $rawPrice['percentage_value'] : $rawPrice['value']);
+        $price->setPriceType(
+            isset($rawPrice['percentage_value'])
+            ? TierPriceInterface::PRICE_TYPE_DISCOUNT
+            : TierPriceInterface::PRICE_TYPE_FIXED
+        );
+        $price->setWebsiteId($rawPrice['website_id']);
+        $price->setSku($sku);
+        $price->setCustomerGroup(
+            $rawPrice['all_groups'] == $this->allGroupsId
+            ? $this->allGroupsValue
+            : $this->customerGroupRepository->getById($rawPrice['customer_group_id'])->getCode()
+        );
+        $price->setQuantity($rawPrice['qty']);
+
+        return $price;
+    }
+
+    /**
+     * Build tier price skeleton that has DB consistent format.
+     *
+     * @param TierPriceInterface $price
+     * @param int $id
+     * @return array
+     */
+    public function createSkeleton(TierPriceInterface $price, $id)
+    {
+        return [
+            $this->tierPricePersistence->getEntityLinkField() => $id,
+            'all_groups' => $this->retrievePriceForAllGroupsValue($price),
+            'customer_group_id' => $this->retrievePriceForAllGroupsValue($price) === $this->allGroupsId
+                ? 0
+                : $this->retrieveGroupValue(strtolower($price->getCustomerGroup())),
+            'qty' => $price->getQuantity(),
+            'value' => $price->getPriceType() === TierPriceInterface::PRICE_TYPE_FIXED
+                ? $price->getPrice()
+                : 0.00,
+            'percentage_value' => $price->getPriceType() === TierPriceInterface::PRICE_TYPE_DISCOUNT
+                ? $price->getPrice()
+                : null,
+            'website_id' => $price->getWebsiteId()
+        ];
+    }
+
+    /**
+     * Retrieve price for all groups value.
+     *
+     * @param TierPriceInterface $price
+     * @return int
+     */
+    private function retrievePriceForAllGroupsValue(TierPriceInterface $price)
+    {
+        return strcasecmp($price->getCustomerGroup(), $this->allGroupsValue) === 0 ? $this->allGroupsId : 0;
+    }
+
+    /**
+     * Retrieve customer group id by code.
+     *
+     * @param string $code
+     * @return int
+     * @throws NoSuchEntityException
+     */
+    private function retrieveGroupValue($code)
+    {
+        if (!isset($this->customerGroupsByCode[$code])) {
+            $searchCriteria = $this->searchCriteriaBuilder->addFilters(
+                [
+                    $this->filterBuilder->setField('customer_group_code')->setValue($code)->create()
+                ]
+            );
+            $items = $this->customerGroupRepository->getList($searchCriteria->create())->getItems();
+            $item = array_shift($items);
+            $this->customerGroupsByCode[strtolower($item->getCode())] = $item->getId();
+        }
+
+        return $this->customerGroupsByCode[$code];
+    }
+}
diff --git a/app/code/Magento/Catalog/Model/Product/Price/TierPricePersistence.php b/app/code/Magento/Catalog/Model/Product/Price/TierPricePersistence.php
new file mode 100644
index 0000000000000000000000000000000000000000..01293d0532fbfc82ed0893436baad30e2baa87b8
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Product/Price/TierPricePersistence.php
@@ -0,0 +1,166 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Model\Product\Price;
+
+/**
+ * Persists tier prices.
+ */
+class TierPricePersistence
+{
+    /**
+     * Number or items per each operation.
+     *
+     * @var int
+     */
+    private $itemsPerOperation = 500;
+
+    /**
+     * Tier price resource model.
+     *
+     * @var \Magento\Catalog\Model\ResourceModel\Product\Attribute\Backend\Tierprice
+     */
+    private $tierpriceResource;
+
+    /**
+     * Metadata pool.
+     *
+     * @var \Magento\Framework\EntityManager\MetadataPool
+     */
+    private $metadataPool;
+
+    /**
+     * TierPricePersister constructor.
+     *
+     * @param \Magento\Catalog\Model\ResourceModel\Product\Attribute\Backend\Tierprice $tierpriceResource
+     * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool
+     */
+    public function __construct(
+        \Magento\Catalog\Model\ResourceModel\Product\Attribute\Backend\Tierprice $tierpriceResource,
+        \Magento\Framework\EntityManager\MetadataPool $metadataPool
+    ) {
+        $this->tierpriceResource = $tierpriceResource;
+        $this->metadataPool = $metadataPool;
+    }
+
+    /**
+     * Get tier prices by product IDs.
+     *
+     * @param array $ids
+     * @return array
+     */
+    public function get(array $ids)
+    {
+        $select = $this->tierpriceResource->getConnection()->select()->from($this->tierpriceResource->getMainTable());
+        return $this->tierpriceResource->getConnection()->fetchAll(
+            $select->where($this->getEntityLinkField() . ' IN (?)', $ids)
+        );
+    }
+
+    /**
+     * Update tier prices.
+     *
+     * @param array $prices
+     * @return void
+     * @throws \Magento\Framework\Exception\CouldNotSaveException
+     */
+    public function update(array $prices)
+    {
+        $connection = $this->tierpriceResource->getConnection();
+        $connection->beginTransaction();
+        try {
+            foreach (array_chunk($prices, $this->itemsPerOperation) as $pricesBunch) {
+                $this->tierpriceResource->getConnection()->insertOnDuplicate(
+                    $this->tierpriceResource->getMainTable(),
+                    $pricesBunch,
+                    ['value', 'percentage_value']
+                );
+            }
+            $connection->commit();
+        } catch (\Exception $e) {
+            $connection->rollBack();
+            throw new \Magento\Framework\Exception\CouldNotSaveException(
+                __('Could not save Tier Prices'),
+                $e
+            );
+        }
+    }
+
+    /**
+     * Replace prices.
+     *
+     * @param array $prices
+     * @param array $ids
+     * @return void
+     * @throws \Magento\Framework\Exception\CouldNotSaveException
+     */
+    public function replace(array $prices, array $ids)
+    {
+        $connection = $this->tierpriceResource->getConnection();
+        $connection->beginTransaction();
+        try {
+            foreach (array_chunk($ids, $this->itemsPerOperation) as $idsBunch) {
+                $this->tierpriceResource->getConnection()->delete(
+                    $this->tierpriceResource->getMainTable(),
+                    [$this->getEntityLinkField() . ' IN (?)' => $idsBunch]
+                );
+            }
+
+            foreach (array_chunk($prices, $this->itemsPerOperation) as $pricesBunch) {
+                $this->tierpriceResource->getConnection()->insertMultiple(
+                    $this->tierpriceResource->getMainTable(),
+                    $pricesBunch
+                );
+            }
+            $connection->commit();
+        } catch (\Exception $e) {
+            $connection->rollBack();
+            throw new \Magento\Framework\Exception\CouldNotSaveException(
+                __('Could not replace Tier Prices'),
+                $e
+            );
+        }
+    }
+
+    /**
+     * Delete tier prices by IDs.
+     *
+     * @param array $ids
+     * @return void
+     * @throws \Magento\Framework\Exception\CouldNotDeleteException
+     */
+    public function delete(array $ids)
+    {
+        $connection = $this->tierpriceResource->getConnection();
+        $connection->beginTransaction();
+        try {
+            foreach (array_chunk($ids, $this->itemsPerOperation) as $idsBunch) {
+                $this->tierpriceResource->getConnection()->delete(
+                    $this->tierpriceResource->getMainTable(),
+                    ['value_id IN (?)' => $idsBunch]
+                );
+            }
+            $connection->commit();
+        } catch (\Exception $e) {
+            $connection->rollBack();
+            throw new \Magento\Framework\Exception\CouldNotDeleteException(
+                __('Could not delete Tier Prices'),
+                $e
+            );
+        }
+    }
+
+    /**
+     * Get link field.
+     *
+     * @return string
+     */
+    public function getEntityLinkField()
+    {
+        return $this->metadataPool->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class)
+            ->getLinkField();
+    }
+}
diff --git a/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php b/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
new file mode 100644
index 0000000000000000000000000000000000000000..83262bbfa1cca6432109f17ef537c4a039c64c04
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
@@ -0,0 +1,323 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Model\Product\Price;
+
+use Magento\Catalog\Api\Data\TierPriceInterface;
+
+/**
+ * Tier price storage.
+ */
+class TierPriceStorage implements \Magento\Catalog\Api\TierPriceStorageInterface
+{
+    /**
+     * Tier price resource model.
+     *
+     * @var TierPricePersistence
+     */
+    private $tierPricePersistence;
+
+    /**
+     * Tier price validator.
+     *
+     * @var \Magento\Catalog\Model\Product\Price\TierPriceValidator
+     */
+    private $tierPriceValidator;
+
+    /**
+     * Tier price builder.
+     *
+     * @var TierPriceFactory
+     */
+    private $tierPriceFactory;
+
+    /**
+     * Price indexer.
+     *
+     * @var \Magento\Catalog\Model\Indexer\Product\Price
+     */
+    private $priceIndexer;
+
+    /**
+     * Product ID locator.
+     *
+     * @var \Magento\Catalog\Model\ProductIdLocatorInterface
+     */
+    private $productIdLocator;
+
+    /**
+     * Page cache config.
+     *
+     * @var \Magento\PageCache\Model\Config
+     */
+    private $config;
+
+    /**
+     * Cache type list.
+     *
+     * @var \Magento\Framework\App\Cache\TypeListInterface
+     */
+    private $typeList;
+
+    /**
+     * Indexer chunk value.
+     *
+     * @var int
+     */
+    private $indexerChunkValue = 500;
+
+    /**
+     * TierPriceStorage constructor.
+     *
+     * @param TierPricePersistence $tierPricePersistence
+     * @param TierPriceValidator $tierPriceValidator
+     * @param TierPriceFactory $tierPriceFactory
+     * @param \Magento\Catalog\Model\Indexer\Product\Price $priceIndexer
+     * @param \Magento\Catalog\Model\ProductIdLocatorInterface $productIdLocator
+     * @param \Magento\PageCache\Model\Config $config
+     * @param \Magento\Framework\App\Cache\TypeListInterface $typeList
+     */
+    public function __construct(
+        TierPricePersistence $tierPricePersistence,
+        TierPriceValidator $tierPriceValidator,
+        TierPriceFactory $tierPriceFactory,
+        \Magento\Catalog\Model\Indexer\Product\Price $priceIndexer,
+        \Magento\Catalog\Model\ProductIdLocatorInterface $productIdLocator,
+        \Magento\PageCache\Model\Config $config,
+        \Magento\Framework\App\Cache\TypeListInterface $typeList
+    ) {
+        $this->tierPricePersistence = $tierPricePersistence;
+        $this->tierPriceValidator = $tierPriceValidator;
+        $this->tierPriceFactory = $tierPriceFactory;
+        $this->priceIndexer = $priceIndexer;
+        $this->productIdLocator = $productIdLocator;
+        $this->config = $config;
+        $this->typeList = $typeList;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function get(array $skus)
+    {
+        $this->tierPriceValidator->validateSkus($skus);
+        $ids = $this->retrieveAffectedIds($skus);
+        $rawPrices = $this->tierPricePersistence->get($ids);
+        $prices = [];
+
+        foreach ($rawPrices as $rawPrice) {
+            $sku = $this->retrieveSkuById($rawPrice[$this->tierPricePersistence->getEntityLinkField()], $skus);
+            $prices[] = $this->tierPriceFactory->create($rawPrice, $sku);
+        }
+
+        return $prices;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function update(array $prices)
+    {
+        $affectedIds = $this->retrieveAffectedProductIdsForPrices($prices);
+        $skus = array_unique(
+            array_map(function ($price) {
+                return $price->getSku();
+            }, $prices)
+        );
+        $this->tierPriceValidator->validatePrices($prices, $this->get($skus));
+        $formattedPrices = $this->retrieveFormattedPrices($prices);
+        $this->tierPricePersistence->update($formattedPrices);
+        $this->reindexPrices($affectedIds);
+        $this->invalidateFullPageCache();
+
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function replace(array $prices)
+    {
+        $this->tierPriceValidator->validatePrices($prices);
+        $affectedIds = $this->retrieveAffectedProductIdsForPrices($prices);
+        $formattedPrices = $this->retrieveFormattedPrices($prices);
+        $this->tierPricePersistence->replace($formattedPrices, $affectedIds);
+        $this->reindexPrices($affectedIds);
+        $this->invalidateFullPageCache();
+
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function delete(array $prices)
+    {
+        $affectedIds = $this->retrieveAffectedProductIdsForPrices($prices);
+        $this->tierPriceValidator->validatePrices($prices);
+        $priceIds = $this->retrieveAffectedPriceIds($prices);
+        $this->tierPricePersistence->delete($priceIds);
+        $this->reindexPrices($affectedIds);
+        $this->invalidateFullPageCache();
+
+        return true;
+    }
+
+    /**
+     * Retrieve formatted prices.
+     *
+     * @param array $prices
+     * @return array
+     */
+    private function retrieveFormattedPrices(array $prices)
+    {
+        $formattedPrices = [];
+
+        foreach ($prices as $price) {
+            $idsBySku = $this->productIdLocator->retrieveProductIdsBySkus([$price->getSku()]);
+            $ids = array_keys($idsBySku[$price->getSku()]);
+            foreach ($ids as $id) {
+                $formattedPrices[] = $this->tierPriceFactory->createSkeleton($price, $id);
+            }
+        }
+
+        return $formattedPrices;
+    }
+
+    /**
+     * Retrieve affected product IDs for prices.
+     *
+     * @param TierPriceInterface[] $prices
+     * @return array
+     */
+    private function retrieveAffectedProductIdsForPrices(array $prices)
+    {
+        $skus = array_unique(
+            array_map(function ($price) {
+                return $price->getSku();
+            }, $prices)
+        );
+
+        return $this->retrieveAffectedIds($skus);
+    }
+
+    /**
+     * Retrieve affected product IDs.
+     *
+     * @param array $skus
+     * @return array
+     */
+    private function retrieveAffectedIds(array $skus)
+    {
+        $affectedIds = [];
+
+        foreach ($this->productIdLocator->retrieveProductIdsBySkus($skus) as $productId) {
+            $affectedIds = array_merge($affectedIds, array_keys($productId));
+        }
+
+        return array_unique($affectedIds);
+    }
+
+    /**
+     * Retrieve affected price IDs.
+     *
+     * @param array $prices
+     * @return array
+     */
+    private function retrieveAffectedPriceIds(array $prices)
+    {
+        $affectedIds = $this->retrieveAffectedProductIdsForPrices($prices);
+        $formattedPrices = $this->retrieveFormattedPrices($prices);
+        $existingPrices = $this->tierPricePersistence->get($affectedIds);
+        $priceIds = [];
+
+        foreach ($formattedPrices as $price) {
+            $priceIds[] = $this->retrievePriceId($price, $existingPrices);
+        }
+
+        return $priceIds;
+    }
+
+    /**
+     * Retrieve price ID.
+     *
+     * @param array $price
+     * @param array $existingPrices
+     * @return int
+     */
+    private function retrievePriceId(array $price, array $existingPrices)
+    {
+        $linkField = $this->tierPricePersistence->getEntityLinkField();
+
+        foreach ($existingPrices as $existingPrice) {
+            if ($existingPrice['all_groups'] == $price['all_groups']
+                && $existingPrice['customer_group_id'] == $price['customer_group_id']
+                && $existingPrice['qty'] == $price['qty']
+                && $this->isCorrectPriceValue($existingPrice, $price)
+                && $existingPrice[$linkField] == $price[$linkField]
+            ) {
+                return $existingPrice['value_id'];
+            }
+        }
+    }
+
+    /**
+     * Check is correct price value
+     *
+     * @param array $existingPrice
+     * @param array $price
+     * @return bool
+     */
+    private function isCorrectPriceValue(array $existingPrice, array $price)
+    {
+        return ($existingPrice['value'] != 0 && $existingPrice['value'] == $price['value'])
+            || ($existingPrice['percentage_value'] !== null
+                && $existingPrice['percentage_value'] == $price['percentage_value']);
+    }
+
+    /**
+     * Retrieve SKU by product ID.
+     *
+     * @param int $id
+     * @param array $skus
+     * @return int|null
+     */
+    private function retrieveSkuById($id, $skus)
+    {
+        foreach ($this->productIdLocator->retrieveProductIdsBySkus($skus) as $sku => $ids) {
+            if (false !== array_key_exists($id, $ids)) {
+                return $sku;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Invalidate full page cache.
+     *
+     * @return void
+     */
+    private function invalidateFullPageCache()
+    {
+        if ($this->config->isEnabled()) {
+            $this->typeList->invalidate('full_page');
+        }
+    }
+
+    /**
+     * Reindex prices.
+     *
+     * @param array $ids
+     * @return void
+     */
+    private function reindexPrices(array $ids)
+    {
+        foreach (array_chunk($ids, $this->indexerChunkValue) as $affectedIds) {
+            $this->priceIndexer->execute($affectedIds);
+        }
+    }
+}
diff --git a/app/code/Magento/Catalog/Model/Product/Price/TierPriceValidator.php b/app/code/Magento/Catalog/Model/Product/Price/TierPriceValidator.php
new file mode 100644
index 0000000000000000000000000000000000000000..907fd0f66bbdd3d02ff288c141361d56fcfe9694
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/Product/Price/TierPriceValidator.php
@@ -0,0 +1,351 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Model\Product\Price;
+
+use Magento\Catalog\Api\Data\TierPriceInterface;
+
+/**
+ * Tier Price Validator.
+ */
+class TierPriceValidator
+{
+    /**
+     * Groups by code cache.
+     *
+     * @var array
+     */
+    private $customerGroupsByCode = [];
+
+    /**
+     * @var TierPricePersistence
+     */
+    private $tierPricePersistence;
+
+    /**
+     * All groups value.
+     *
+     * @var string
+     */
+    private $allGroupsValue = 'all groups';
+
+    /**
+     * All websites value.
+     *
+     * @var string
+     */
+    private $allWebsitesValue = "0";
+
+    /**
+     * Allowed product types.
+     *
+     * @var array
+     */
+    private $allowedProductTypes = [];
+
+    /**
+     * TierPriceValidator constructor.
+     *
+     * @param \Magento\Catalog\Model\ProductIdLocatorInterface $productIdLocator
+     * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
+     * @param \Magento\Framework\Api\FilterBuilder $filterBuilder
+     * @param \Magento\Customer\Api\GroupRepositoryInterface $customerGroupRepository
+     * @param \Magento\Store\Api\WebsiteRepositoryInterface $websiteRepository
+     * @param TierPricePersistence $tierPricePersistence
+     * @param array $allowedProductTypes
+     */
+    public function __construct(
+        \Magento\Catalog\Model\ProductIdLocatorInterface $productIdLocator,
+        \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
+        \Magento\Framework\Api\FilterBuilder $filterBuilder,
+        \Magento\Customer\Api\GroupRepositoryInterface $customerGroupRepository,
+        \Magento\Store\Api\WebsiteRepositoryInterface $websiteRepository,
+        TierPricePersistence $tierPricePersistence,
+        array $allowedProductTypes = []
+    ) {
+        $this->productIdLocator = $productIdLocator;
+        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
+        $this->filterBuilder = $filterBuilder;
+        $this->customerGroupRepository = $customerGroupRepository;
+        $this->websiteRepository = $websiteRepository;
+        $this->tierPricePersistence = $tierPricePersistence;
+        $this->allowedProductTypes = $allowedProductTypes;
+    }
+
+    /**
+     * Validate SKU.
+     *
+     * @param array $skus
+     * @throws \Magento\Framework\Exception\LocalizedException
+     * @return void
+     */
+    public function validateSkus(array $skus)
+    {
+        $idsBySku = $this->productIdLocator->retrieveProductIdsBySkus($skus);
+        $skuDiff = array_diff($skus, array_keys($idsBySku));
+
+        foreach ($idsBySku as $sku => $ids) {
+            foreach (array_values($ids) as $type) {
+                if (!in_array($type, $this->allowedProductTypes)) {
+                    $skuDiff[] = $sku;
+                    break;
+                }
+            }
+        }
+
+        if (!empty($skuDiff)) {
+            $values = implode(', ', $skuDiff);
+            $description = count($skuDiff) == 1
+                ? __('Requested product doesn\'t exist: %1', $values)
+                : __('Requested products don\'t exist: %1', $values);
+            throw new \Magento\Framework\Exception\NoSuchEntityException($description);
+        }
+    }
+
+    /**
+     * Validate that prices have appropriate values and are unique.
+     *
+     * @param array $prices
+     * @param array $existingPrices
+     * @return void
+     * @throws \Magento\Framework\Exception\LocalizedException
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function validatePrices(array $prices, array $existingPrices = [])
+    {
+        $skus = array_unique(
+            array_map(function ($price) {
+                if (!$price->getSku()) {
+                    throw new \Magento\Framework\Exception\LocalizedException(
+                        __(
+                            'Invalid attribute %fieldName: %fieldValue.',
+                            [
+                                'fieldName' => 'sku',
+                                'fieldValue' => $price->getSku()
+                            ]
+                        )
+                    );
+                }
+                return $price->getSku();
+            }, $prices)
+        );
+        $this->validateSkus($skus);
+        $idsBySku = $this->productIdLocator->retrieveProductIdsBySkus($skus);
+
+        $pricesBySku = [];
+
+        foreach ($prices as $price) {
+            $pricesBySku[$price->getSku()][] = $price;
+        }
+
+        /** @var TierPriceInterface $price */
+        foreach ($prices as $price) {
+            $this->checkPrice($price);
+            $this->checkPriceType($price, $idsBySku[$price->getSku()]);
+            $this->checkQuantity($price);
+            $this->checkWebsite($price);
+            if (isset($pricesBySku[$price->getSku()])) {
+                $this->checkUnique($price, $pricesBySku[$price->getSku()]);
+            }
+            $this->checkUnique($price, $existingPrices);
+            $this->checkGroup($price);
+        }
+    }
+
+    /**
+     * Verify that price value is correct.
+     *
+     * @param TierPriceInterface $price
+     * @throws \Magento\Framework\Exception\LocalizedException
+     * @return void
+     */
+    private function checkPrice(TierPriceInterface $price)
+    {
+        if (
+            null === $price->getPrice()
+            || $price->getPrice() < 0
+            || ($price->getPriceType() === TierPriceInterface::PRICE_TYPE_DISCOUNT && $price->getPrice() > 100)
+        ) {
+            throw new \Magento\Framework\Exception\LocalizedException(
+                __(
+                    'Invalid attribute %fieldName: %fieldValue.',
+                    [
+                        'fieldName' => 'Price',
+                        'fieldValue' => $price->getPrice()
+                    ]
+                )
+            );
+        }
+    }
+
+    /**
+     * Verify that price type is correct.
+     *
+     * @param TierPriceInterface $price
+     * @param array $ids
+     * @throws \Magento\Framework\Exception\LocalizedException
+     * @return void
+     */
+    private function checkPriceType(TierPriceInterface $price, array $ids)
+    {
+        if (
+            !in_array(
+                $price->getPriceType(),
+                [TierPriceInterface::PRICE_TYPE_FIXED, TierPriceInterface::PRICE_TYPE_DISCOUNT]
+            )
+            || (array_search(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE, $ids)
+                && $price->getPriceType() !== TierPriceInterface::PRICE_TYPE_DISCOUNT)
+        ) {
+            throw new \Magento\Framework\Exception\LocalizedException(
+                __(
+                    'Invalid attribute %fieldName: %fieldValue.',
+                    [
+                        'fieldName' => 'Price Type',
+                        'fieldValue' => $price->getPriceType()
+                    ]
+                )
+            );
+        }
+    }
+
+    /**
+     * Verify that product quantity is correct.
+     *
+     * @param TierPriceInterface $price
+     * @throws \Magento\Framework\Exception\LocalizedException
+     * @return void
+     */
+    private function checkQuantity(TierPriceInterface $price)
+    {
+        if ($price->getQuantity() < 1) {
+            throw new \Magento\Framework\Exception\LocalizedException(
+                __(
+                    'Invalid attribute %fieldName: %fieldValue.',
+                    [
+                        'fieldName' => 'Quantity',
+                        'fieldValue' => $price->getQuantity()
+                    ]
+                )
+            );
+        }
+    }
+
+    /**
+     * Verify that website exists.
+     *
+     * @param TierPriceInterface $price
+     * @return void
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    private function checkWebsite(TierPriceInterface $price)
+    {
+        try {
+            $this->websiteRepository->getById($price->getWebsiteId());
+        } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
+            throw new \Magento\Framework\Exception\NoSuchEntityException(
+                __(
+                    'Invalid attribute %fieldName: %fieldValue.',
+                    [
+                        'fieldName' => 'website_id',
+                        'fieldValue' => $price->getWebsiteId()
+                    ]
+                )
+            );
+        }
+    }
+
+    /**
+     * Check website value is unique.
+     *
+     * @param TierPriceInterface $tierPrice
+     * @param array $prices
+     * @return void
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    private function checkUnique(TierPriceInterface $tierPrice, array $prices)
+    {
+        /** @var TierPriceInterface $price */
+        foreach ($prices as $price) {
+            if (
+                $price->getSku() === $tierPrice->getSku()
+                && $price->getCustomerGroup() === $tierPrice->getCustomerGroup()
+                && $price->getQuantity() == $tierPrice->getQuantity()
+                && (
+                    ($price->getWebsiteId() == $this->allWebsitesValue
+                        || $tierPrice->getWebsiteId() == $this->allWebsitesValue)
+                    && $price->getWebsiteId() != $tierPrice->getWebsiteId()
+                )
+            ) {
+                throw new \Magento\Framework\Exception\LocalizedException(
+                    __(
+                        'We found a duplicate website, tier price, customer group and quantity: '
+                        . '%fieldName1 = %fieldValue1, %fieldName2 = %fieldValue2, %fieldName3 = %fieldValue3.',
+                        [
+                            'fieldName1' => 'Customer Group',
+                            'fieldValue1' => $price->getCustomerGroup(),
+                            'fieldName2' => 'Website Id',
+                            'fieldValue2' => $price->getWebsiteId(),
+                            'fieldName3' => 'Quantity',
+                            'fieldValue3' => $price->getQuantity()
+                        ]
+                    )
+                );
+            }
+        }
+    }
+
+    /**
+     * Check customer group exists and has correct value.
+     *
+     * @param TierPriceInterface $price
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     * @return void
+     */
+    private function checkGroup(TierPriceInterface $price)
+    {
+        $customerGroup = strtolower($price->getCustomerGroup());
+
+        if ($customerGroup != $this->allGroupsValue) {
+            $this->retrieveGroupValue($customerGroup);
+        }
+    }
+
+    /**
+     * Retrieve customer group id by code.
+     *
+     * @param string $code
+     * @return int
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     */
+    private function retrieveGroupValue($code)
+    {
+        if (!isset($this->customerGroupsByCode[$code])) {
+            $searchCriteria = $this->searchCriteriaBuilder->addFilters(
+                [
+                    $this->filterBuilder->setField('customer_group_code')->setValue($code)->create()
+                ]
+            );
+            $items = $this->customerGroupRepository->getList($searchCriteria->create())->getItems();
+            $item = array_shift($items);
+
+            if (!$item) {
+                throw new \Magento\Framework\Exception\NoSuchEntityException(
+                    __(
+                        'No such entity with %fieldName = %fieldValue.',
+                        [
+                            'fieldName' => 'Customer Group',
+                            'fieldValue' => $code
+                        ]
+                    )
+                );
+            }
+
+            $this->customerGroupsByCode[strtolower($item->getCode())] = $item->getId();
+        }
+
+        return $this->customerGroupsByCode[$code];
+    }
+}
diff --git a/app/code/Magento/Catalog/Model/Product/Type/Price.php b/app/code/Magento/Catalog/Model/Product/Type/Price.php
index af15e049203f3f6aae27ef2c6ff071d49cdab8cd..13dfdfe6e5cdc457e751348991fbb806e02ccb12 100644
--- a/app/code/Magento/Catalog/Model/Product/Type/Price.php
+++ b/app/code/Magento/Catalog/Model/Product/Type/Price.php
@@ -414,11 +414,12 @@ class Price
         $prices = [];
         foreach ($tierPrices as $price) {
             $extensionAttributes = $price->getExtensionAttributes();
-            $websiteId = $extensionAttributes && $extensionAttributes->getWebsiteId()
-                ? $extensionAttributes->getWebsiteId()
-                : $websiteId;
+            $priceWebsiteId = $websiteId;
+            if (isset($extensionAttributes) && is_numeric($extensionAttributes->getWebsiteId())) {
+                $priceWebsiteId = (string)$extensionAttributes->getWebsiteId();
+            }
             $prices[] = [
-                'website_id' => $websiteId,
+                'website_id' => $priceWebsiteId,
                 'cust_group' => $price->getCustomerGroupId(),
                 'website_price' => $price->getValue(),
                 'price' => $price->getValue(),
diff --git a/app/code/Magento/Catalog/Model/ProductIdLocator.php b/app/code/Magento/Catalog/Model/ProductIdLocator.php
new file mode 100644
index 0000000000000000000000000000000000000000..1678ecd23c9262229ab063c2ad5af65abad9b49d
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/ProductIdLocator.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Model;
+
+/**
+ * Product ID locator provides all product IDs by SKUs.
+ * @api
+ */
+class ProductIdLocator implements \Magento\Catalog\Model\ProductIdLocatorInterface
+{
+    /**
+     * Search Criteria builder.
+     *
+     * @var \Magento\Framework\Api\SearchCriteriaBuilder
+     */
+    private $searchCriteriaBuilder;
+
+    /**
+     * Filter builder.
+     *
+     * @var \Magento\Framework\Api\FilterBuilder
+     */
+    private $filterBuilder;
+
+    /**
+     * Metadata pool.
+     *
+     * @var \Magento\Framework\EntityManager\MetadataPool
+     */
+    private $metadataPool;
+
+    /**
+     * Product repository.
+     *
+     * @var \Magento\Catalog\Api\ProductRepositoryInterface
+     */
+    private $productRepository;
+
+    /**
+     * IDs by SKU cache.
+     *
+     * @var array
+     */
+    private $idsBySku = [];
+
+    /**
+     * ProductIdLocatorInterface constructor.
+     *
+     * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
+     * @param \Magento\Framework\Api\FilterBuilder $filterBuilder
+     * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool
+     * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
+     */
+    public function __construct(
+        \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
+        \Magento\Framework\Api\FilterBuilder $filterBuilder,
+        \Magento\Framework\EntityManager\MetadataPool $metadataPool,
+        \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
+    ) {
+        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
+        $this->filterBuilder = $filterBuilder;
+        $this->metadataPool = $metadataPool;
+        $this->productRepository = $productRepository;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function retrieveProductIdsBySkus(array $skus)
+    {
+        $skus = array_map('trim', $skus);
+        $skusInCache = $this->idsBySku ? array_keys($this->idsBySku) : [];
+        $neededSkus = array_diff($skus, $skusInCache);
+
+        if (!empty($neededSkus)) {
+            $searchCriteria = $this->searchCriteriaBuilder->addFilters(
+                [
+                    $this->filterBuilder
+                        ->setField(\Magento\Catalog\Api\Data\ProductInterface::SKU)
+                        ->setConditionType('in')
+                        ->setValue($neededSkus)
+                        ->create(),
+                ]
+            );
+            $items = $this->productRepository->getList($searchCriteria->create())->getItems();
+            $linkField = $this->metadataPool->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class)
+                ->getLinkField();
+
+            foreach ($items as $item) {
+                $this->idsBySku[$item->getSku()][$item->getData($linkField)] = $item->getTypeId();
+            }
+        }
+
+        return array_intersect_key($this->idsBySku, array_flip($skus));
+    }
+}
diff --git a/app/code/Magento/Catalog/Model/ProductIdLocatorInterface.php b/app/code/Magento/Catalog/Model/ProductIdLocatorInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..f9a0d88df2eac54e741478d803891f9eb1214152
--- /dev/null
+++ b/app/code/Magento/Catalog/Model/ProductIdLocatorInterface.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Catalog\Model;
+
+/**
+ * Product ID locator provides all product IDs by SKU.
+ */
+interface ProductIdLocatorInterface
+{
+    /**
+     * Will return associative array of product ids as key and type as value grouped by SKUs.
+     *
+     * @param array $skus
+     * @return array
+     */
+    public function retrieveProductIdsBySkus(array $skus);
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/BasePriceStorageTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/BasePriceStorageTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ef99e550cdc21ad00f9a726d149528af24ce59c5
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/BasePriceStorageTest.php
@@ -0,0 +1,326 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\Unit\Model\Product\Price;
+
+/**
+ * Class BasePriceStorageTest.
+ */
+class BasePriceStorageTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Product\Price\PricePersistenceFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $pricePersistenceFactory;
+
+    /**
+     * @var \Magento\Catalog\Model\Product\Price\PricePersistence|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $pricePersistence;
+
+    /**
+     * @var \Magento\Catalog\Api\Data\BasePriceInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $basePriceInterfaceFactory;
+
+    /**
+     * @var \Magento\Catalog\Api\Data\BasePriceInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $basePriceInterface;
+
+    /**
+     * @var \Magento\Catalog\Model\ProductIdLocatorInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productIdLocator;
+
+    /**
+     * @var \Magento\Store\Api\StoreRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $storeRepository;
+
+    /**
+     * @var \Magento\Catalog\Api\ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productRepository;
+
+    /**
+     * @var \Magento\Catalog\Api\Data\ProductInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $product;
+
+    /**
+     * @var \Magento\Catalog\Model\Product\Price\BasePriceStorage
+     */
+    private $model;
+
+    /**
+     * Set up.
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->pricePersistenceFactory = $this->getMock(
+            \Magento\Catalog\Model\Product\Price\PricePersistenceFactory::class,
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->pricePersistence = $this->getMock(
+            \Magento\Catalog\Model\Product\Price\PricePersistence::class,
+            ['get', 'retrieveSkuById', 'update', 'getEntityLinkField'],
+            [],
+            '',
+            false
+        );
+        $this->basePriceInterfaceFactory = $this->getMock(
+            \Magento\Catalog\Api\Data\BasePriceInterfaceFactory::class,
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->basePriceInterface = $this->getMockForAbstractClass(
+            \Magento\Catalog\Api\Data\BasePriceInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['setSku', 'setPrice', 'setStoreId', 'getSku', 'getPrice', 'getStoreId']
+        );
+        $this->productIdLocator = $this->getMockForAbstractClass(
+            \Magento\Catalog\Model\ProductIdLocatorInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['retrieveProductIdsBySkus']
+        );
+        $this->storeRepository = $this->getMockForAbstractClass(
+            \Magento\Store\Api\StoreRepositoryInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getById']
+        );
+        $this->productRepository = $this->getMockForAbstractClass(
+            \Magento\Catalog\Api\ProductRepositoryInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['get']
+        );
+        $this->product = $this->getMockForAbstractClass(
+            \Magento\Catalog\Api\Data\ProductInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getPriceType']
+        );
+
+        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+        $this->model = $objectManager->getObject(
+            \Magento\Catalog\Model\Product\Price\BasePriceStorage::class,
+            [
+                'pricePersistenceFactory' => $this->pricePersistenceFactory,
+                'basePriceInterfaceFactory' => $this->basePriceInterfaceFactory,
+                'productIdLocator' => $this->productIdLocator,
+                'storeRepository' => $this->storeRepository,
+                'productRepository' => $this->productRepository,
+                'allowedProductTypes' => ['simple', 'virtual', 'bundle', 'downloadable'],
+            ]
+        );
+    }
+
+    /**
+     * Test get method.
+     *
+     * @return void
+     */
+    public function testGet()
+    {
+        $skus = ['sku_1', 'sku_2'];
+        $idsBySku = [
+            'sku_1' =>
+                [
+                    1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE
+                ],
+            'sku_2' =>
+                [
+                    2 => \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE
+                ]
+        ];
+        $rawPrices = [
+            [
+                'row_id' => 1,
+                'value' => 15,
+                'store_id' => 1
+            ],
+            [
+                'row_id' => 2,
+                'value' => 35,
+                'store_id' => 1
+            ]
+        ];
+        $this->productIdLocator
+            ->expects($this->once())
+            ->method('retrieveProductIdsBySkus')->with($skus)
+            ->willReturn($idsBySku);
+        $this->productRepository->expects($this->once())->method('get')->willReturn($this->product);
+        $this->product->expects($this->once())->method('getPriceType')->willReturn(1);
+        $this->pricePersistenceFactory
+            ->expects($this->once())
+            ->method('create')
+            ->with(['attributeCode' => 'price'])
+            ->willReturn($this->pricePersistence);
+        $this->pricePersistence->expects($this->once())->method('get')->with($skus)->willReturn($rawPrices);
+        $this->pricePersistence->expects($this->atLeastOnce())->method('getEntityLinkField')->willReturn('row_id');
+        $this->basePriceInterfaceFactory
+            ->expects($this->exactly(2))
+            ->method('create')
+            ->willReturn($this->basePriceInterface);
+        $this->pricePersistence
+            ->expects($this->exactly(2))
+            ->method('retrieveSkuById')
+            ->willReturnOnConsecutiveCalls('sku_1', 'sku_2');
+        $this->basePriceInterface
+            ->expects($this->exactly(2))
+            ->method('setSku')
+            ->withConsecutive(['sku_1'], ['sku_2'])
+            ->willReturnSelf();
+        $this->basePriceInterface
+            ->expects($this->exactly(2))
+            ->method('setPrice')
+            ->withConsecutive([15], [35])
+            ->willReturnSelf();
+        $this->basePriceInterface
+            ->expects($this->exactly(2))
+            ->method('setStoreId')
+            ->withConsecutive([1], [1])
+            ->willReturnSelf();
+        $this->model->get($skus);
+    }
+
+    /**
+     * Test get method with exception.
+     *
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     * @expectedExceptionMessage Requested products don't exist: sku_1, sku_2
+     */
+    public function testGetWithException()
+    {
+        $skus = ['sku_1', 'sku_2'];
+        $idsBySku = [
+            'sku_1' =>
+                [
+                    1 => 'configurable'
+                ],
+            'sku_2' =>
+                [
+                    2 => 'grouped'
+                ]
+        ];
+        $this->productIdLocator
+            ->expects($this->once())
+            ->method('retrieveProductIdsBySkus')->with($skus)
+            ->willReturn($idsBySku);
+        $this->model->get($skus);
+    }
+
+    /**
+     * Test update method.
+     *
+     * @return void
+     */
+    public function testUpdate()
+    {
+        $store = $this->getMockForAbstractClass(
+            \Magento\Store\Api\Data\StoreInterface::class,
+            [],
+            '',
+            false
+        );
+        $sku = 'sku_1';
+        $idsBySku = [
+            'sku_1' =>
+                [
+                    1 => \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE
+                ]
+        ];
+        $this->basePriceInterface->expects($this->exactly(4))->method('getSku')->willReturn($sku);
+        $this->productIdLocator
+            ->expects($this->exactly(2))
+            ->method('retrieveProductIdsBySkus')->with([$sku])
+            ->willReturn($idsBySku);
+        $this->productRepository->expects($this->once())->method('get')->willReturn($this->product);
+        $this->product->expects($this->once())->method('getPriceType')->willReturn(1);
+        $this->basePriceInterface->expects($this->exactly(3))->method('getPrice')->willReturn(15);
+        $this->basePriceInterface->expects($this->exactly(2))->method('getStoreId')->willReturn(1);
+        $this->pricePersistence->expects($this->atLeastOnce())->method('getEntityLinkField')->willReturn('row_id');
+        $this->storeRepository->expects($this->once())->method('getById')->with(1)->willReturn($store);
+        $this->pricePersistenceFactory
+            ->expects($this->once())
+            ->method('create')
+            ->with(['attributeCode' => 'price'])
+            ->willReturn($this->pricePersistence);
+        $formattedPrices = [
+            [
+                'store_id' => 1,
+                'row_id' => 1,
+                'value' => 15
+            ]
+        ];
+        $this->pricePersistence->expects($this->once())->method('update')->with($formattedPrices);
+        $this->assertTrue($this->model->update([$this->basePriceInterface]));
+    }
+
+    /**
+     * Test update method without SKU.
+     *
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @expectedExceptionMessage Invalid attribute sku: .
+     */
+    public function testUpdateWithoutSku()
+    {
+        $this->basePriceInterface->expects($this->exactly(2))->method('getSku')->willReturn(null);
+        $this->model->update([$this->basePriceInterface]);
+    }
+
+    /**
+     * Test update method with negative price.
+     *
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @expectedExceptionMessage Invalid attribute Price: -15.
+     */
+    public function testUpdateWithNegativePrice()
+    {
+        $sku = 'sku_1';
+        $idsBySku = [
+            'sku_1' =>
+                [
+                    1 => \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE
+                ]
+        ];
+        $this->basePriceInterface->expects($this->exactly(2))->method('getSku')->willReturn($sku);
+        $this->productIdLocator
+            ->expects($this->once(1))
+            ->method('retrieveProductIdsBySkus')->with([$sku])
+            ->willReturn($idsBySku);
+        $this->productRepository->expects($this->once())->method('get')->willReturn($this->product);
+        $this->product->expects($this->once())->method('getPriceType')->willReturn(1);
+        $this->basePriceInterface->expects($this->exactly(3))->method('getPrice')->willReturn(-15);
+        $this->model->update([$this->basePriceInterface]);
+    }
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/CostStorageTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/CostStorageTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b1dea66928f1bd98788758420167bde6dcca2329
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/CostStorageTest.php
@@ -0,0 +1,322 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\Unit\Model\Product\Price;
+
+/**
+ * Class CostStorageTest.
+ */
+class CostStorageTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Product\Price\PricePersistenceFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $pricePersistenceFactory;
+
+    /**
+     * @var \Magento\Catalog\Model\Product\Price\PricePersistence|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $pricePersistence;
+
+    /**
+     * @var \Magento\Catalog\Api\Data\CostInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $costInterfaceFactory;
+
+    /**
+     * @var \Magento\Catalog\Api\Data\CostInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $costInterface;
+
+    /**
+     * @var \Magento\Catalog\Model\ProductIdLocatorInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productIdLocator;
+
+    /**
+     * @var \Magento\Store\Api\StoreRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $storeRepository;
+
+    /**
+     * @var \Magento\Catalog\Model\Product\Price\CostStorage
+     */
+    private $model;
+
+    /**
+     * Set up.
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->pricePersistenceFactory = $this->getMock(
+            \Magento\Catalog\Model\Product\Price\PricePersistenceFactory::class,
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->pricePersistence = $this->getMock(
+            \Magento\Catalog\Model\Product\Price\PricePersistence::class,
+            ['get', 'retrieveSkuById', 'update', 'delete', 'getEntityLinkField'],
+            [],
+            '',
+            false
+        );
+        $this->costInterfaceFactory = $this->getMock(
+            \Magento\Catalog\Api\Data\CostInterfaceFactory::class,
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->costInterface = $this->getMockForAbstractClass(
+            \Magento\Catalog\Api\Data\CostInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['setSku', 'setCost', 'setStoreId', 'getSku', 'getCost', 'getStoreId']
+        );
+        $this->productIdLocator = $this->getMockForAbstractClass(
+            \Magento\Catalog\Model\ProductIdLocatorInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['retrieveProductIdsBySkus']
+        );
+        $this->storeRepository = $this->getMockForAbstractClass(
+            \Magento\Store\Api\StoreRepositoryInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getById']
+        );
+
+        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+        $this->model = $objectManager->getObject(
+            \Magento\Catalog\Model\Product\Price\CostStorage::class,
+            [
+                'pricePersistenceFactory' => $this->pricePersistenceFactory,
+                'costInterfaceFactory' => $this->costInterfaceFactory,
+                'productIdLocator' => $this->productIdLocator,
+                'storeRepository' => $this->storeRepository,
+                'allowedProductTypes' => ['simple', 'virtual', 'downloadable'],
+            ]
+        );
+    }
+
+    /**
+     * Test get method.
+     *
+     * @return void
+     */
+    public function testGet()
+    {
+        $skus = ['sku_1', 'sku_2'];
+        $idsBySku = [
+            'sku_1' =>
+                [
+                    1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE
+                ],
+            'sku_2' =>
+                [
+                    2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL
+                ]
+        ];
+        $rawPrices = [
+            [
+                'row_id' => 1,
+                'value' => 15,
+                'store_id' => 1
+            ],
+            [
+                'row_id' => 2,
+                'value' => 35,
+                'store_id' => 1
+            ]
+        ];
+        $this->productIdLocator
+            ->expects($this->once())
+            ->method('retrieveProductIdsBySkus')->with($skus)
+            ->willReturn($idsBySku);
+        $this->pricePersistenceFactory
+            ->expects($this->once())
+            ->method('create')
+            ->with(['attributeCode' => 'cost'])
+            ->willReturn($this->pricePersistence);
+        $this->pricePersistence->expects($this->once())->method('get')->with($skus)->willReturn($rawPrices);
+        $this->costInterfaceFactory
+            ->expects($this->exactly(2))
+            ->method('create')
+            ->willReturn($this->costInterface);
+        $this->pricePersistence
+            ->expects($this->exactly(2))
+            ->method('retrieveSkuById')
+            ->willReturnOnConsecutiveCalls('sku_1', 'sku_2');
+        $this->pricePersistence->expects($this->atLeastOnce())->method('getEntityLinkField')->willReturn('row_id');
+        $this->costInterface
+            ->expects($this->exactly(2))
+            ->method('setSku')
+            ->withConsecutive(['sku_1'], ['sku_2'])
+            ->willReturnSelf();
+        $this->costInterface
+            ->expects($this->exactly(2))
+            ->method('setCost')
+            ->withConsecutive([15], [35])
+            ->willReturnSelf();
+        $this->costInterface
+            ->expects($this->exactly(2))
+            ->method('setStoreId')
+            ->withConsecutive([1], [1])
+            ->willReturnSelf();
+        $this->model->get($skus);
+    }
+
+    /**
+     * Test get method with exception.
+     *
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     * @expectedExceptionMessage Requested products don't exist: sku_1, sku_2
+     */
+    public function testGetWithException()
+    {
+        $skus = ['sku_1', 'sku_2'];
+        $idsBySku = [
+            'sku_1' =>
+                [
+                    1 => 'configurable'
+                ],
+            'sku_2' =>
+                [
+                    2 => 'grouped'
+                ]
+        ];
+        $this->productIdLocator
+            ->expects($this->once())
+            ->method('retrieveProductIdsBySkus')->with($skus)
+            ->willReturn($idsBySku);
+        $this->model->get($skus);
+    }
+
+    /**
+     * Test update method.
+     *
+     * @return void
+     */
+    public function testUpdate()
+    {
+        $store = $this->getMockForAbstractClass(
+            \Magento\Store\Api\Data\StoreInterface::class,
+            [],
+            '',
+            false
+        );
+        $sku = 'sku_1';
+        $idsBySku = [
+            'sku_1' =>
+                [
+                    1 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL
+                ]
+        ];
+        $this->costInterface->expects($this->exactly(4))->method('getSku')->willReturn($sku);
+        $this->productIdLocator
+            ->expects($this->exactly(2))
+            ->method('retrieveProductIdsBySkus')->with([$sku])
+            ->willReturn($idsBySku);
+        $this->costInterface->expects($this->exactly(3))->method('getCost')->willReturn(15);
+        $this->costInterface->expects($this->exactly(2))->method('getStoreId')->willReturn(1);
+        $this->pricePersistence->expects($this->atLeastOnce())->method('getEntityLinkField')->willReturn('row_id');
+        $this->storeRepository->expects($this->once())->method('getById')->with(1)->willReturn($store);
+        $this->pricePersistenceFactory
+            ->expects($this->once())
+            ->method('create')
+            ->with(['attributeCode' => 'cost'])
+            ->willReturn($this->pricePersistence);
+        $formattedPrices = [
+            [
+                'store_id' => 1,
+                'row_id' => 1,
+                'value' => 15
+            ]
+        ];
+        $this->pricePersistence->expects($this->once())->method('update')->with($formattedPrices);
+        $this->assertTrue($this->model->update([$this->costInterface]));
+    }
+
+    /**
+     * Test update method without SKU.
+     *
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @expectedExceptionMessage Invalid attribute sku: .
+     */
+    public function testUpdateWithoutSku()
+    {
+        $this->costInterface->expects($this->exactly(2))->method('getSku')->willReturn(null);
+        $this->model->update([$this->costInterface]);
+    }
+
+    /**
+     * Test update method with negative cost.
+     *
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @expectedExceptionMessage Invalid attribute Cost: -15.
+     */
+    public function testUpdateWithNegativeCost()
+    {
+        $sku = 'sku_1';
+        $idsBySku = [
+            'sku_1' =>
+                [
+                    1 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL
+                ]
+        ];
+        $this->costInterface->expects($this->exactly(2))->method('getSku')->willReturn($sku);
+        $this->productIdLocator
+            ->expects($this->once(1))
+            ->method('retrieveProductIdsBySkus')->with([$sku])
+            ->willReturn($idsBySku);
+        $this->costInterface->expects($this->exactly(3))->method('getCost')->willReturn(-15);
+        $this->model->update([$this->costInterface]);
+    }
+
+    /**
+     * Test delete method.
+     *
+     * @return void
+     */
+    public function testDelete()
+    {
+        $skus = ['sku_1', 'sku_2'];
+        $idsBySku = [
+            'sku_1' =>
+                [
+                    1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE
+                ],
+            'sku_2' =>
+                [
+                    2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL
+                ]
+        ];
+        $this->productIdLocator
+            ->expects($this->once())
+            ->method('retrieveProductIdsBySkus')->with($skus)
+            ->willReturn($idsBySku);
+        $this->pricePersistenceFactory
+            ->expects($this->once())
+            ->method('create')
+            ->with(['attributeCode' => 'cost'])
+            ->willReturn($this->pricePersistence);
+        $this->pricePersistence->expects($this->once())->method('delete')->with($skus);
+        $this->model->delete($skus);
+    }
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/PricePersistenceTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/PricePersistenceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e9f422245d95967905b577c7cc39626007b16d49
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/PricePersistenceTest.php
@@ -0,0 +1,402 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\Unit\Model\Product\Price;
+
+/**
+ * Class PricePersistenceTest.
+ */
+class PricePersistenceTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\ResourceModel\Attribute|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $attributeResource;
+
+    /**
+     * @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $attributeRepository;
+
+    /**
+     * @var \Magento\Catalog\Api\Data\ProductAttributeInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productAttribute;
+
+    /**
+     * @var \Magento\Catalog\Model\ProductIdLocatorInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productIdLocator;
+
+    /**
+     * @var \Magento\Framework\DB\Adapter\AdapterInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $connection;
+
+    /**
+     * @var \Magento\Framework\EntityManager\MetadataPool|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $metadataPool;
+
+    /**
+     * @var \Magento\Catalog\Model\Product\Price\PricePersistence
+     */
+    private $model;
+
+    /**
+     * Set up.
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->attributeResource = $this->getMock(
+            \Magento\Catalog\Model\ResourceModel\Attribute::class,
+            ['getConnection', 'getTable'],
+            [],
+            '',
+            false
+        );
+        $this->attributeRepository = $this->getMockForAbstractClass(
+            \Magento\Catalog\Api\ProductAttributeRepositoryInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['get']
+        );
+        $this->productIdLocator = $this->getMockForAbstractClass(
+            \Magento\Catalog\Model\ProductIdLocatorInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['retrieveProductIdsBySkus']
+        );
+        $this->metadataPool = $this->getMock(
+            \Magento\Framework\EntityManager\MetadataPool::class,
+            ['getLinkField', 'getMetadata'],
+            [],
+            '',
+            false
+        );
+        $this->connection = $this->getMockForAbstractClass(
+            \Magento\Framework\DB\Adapter\AdapterInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['select', 'fetchAll', 'beginTransaction', 'insertOnDuplicate', 'commit', 'rollBack', 'delete']
+        );
+        $this->productAttribute = $this->getMockForAbstractClass(
+            \Magento\Catalog\Api\Data\ProductAttributeInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getAttributeId']
+        );
+
+        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+        $this->model = $objectManager->getObject(
+            \Magento\Catalog\Model\Product\Price\PricePersistence::class,
+            [
+                'attributeResource' => $this->attributeResource,
+                'attributeRepository' => $this->attributeRepository,
+                'productIdLocator' => $this->productIdLocator,
+                'metadataPool' => $this->metadataPool,
+            ]
+        );
+    }
+
+    /**
+     * Test get method.
+     *
+     * @return void
+     */
+    public function testGet()
+    {
+        $attributeId = 5;
+        $skus = ['sku_1', 'sku_2'];
+        $idsBySku = [
+            'sku_1' =>
+                [
+                    1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE
+                ],
+            'sku_2' =>
+                [
+                    2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL
+                ]
+        ];
+        $select = $this->getMock(
+            \Magento\Framework\DB\Select::class,
+            ['from', 'where'],
+            [],
+            '',
+            false
+        );
+        $this->productIdLocator
+            ->expects($this->once())
+            ->method('retrieveProductIdsBySkus')->with($skus)
+            ->willReturn($idsBySku);
+        $this->attributeResource->expects($this->exactly(2))->method('getConnection')->willReturn($this->connection);
+        $this->connection->expects($this->once())->method('select')->willReturn($select);
+        $this->attributeResource
+            ->expects($this->once())
+            ->method('getTable')
+            ->with('catalog_product_entity_decimal')
+            ->willReturn('catalog_product_entity_decimal');
+        $select->expects($this->once())->method('from')->with('catalog_product_entity_decimal')->willReturnSelf();
+        $this->attributeRepository->expects($this->once())->method('get')->willReturn($this->productAttribute);
+        $this->productAttribute->expects($this->once())->method('getAttributeId')->willReturn($attributeId);
+        $select
+            ->expects($this->exactly(2))
+            ->method('where')
+            ->withConsecutive(['row_id IN (?)', [1, 2]], ['attribute_id = ?', $attributeId])
+            ->willReturnSelf();
+        $this->metadataPool->expects($this->atLeastOnce())->method('getMetadata')->willReturnSelf();
+        $this->metadataPool->expects($this->atLeastOnce())->method('getLinkField')->willReturn('row_id');
+        $this->model->get($skus);
+    }
+
+    /**
+     * Test update method.
+     *
+     * @return void
+     */
+    public function testUpdate()
+    {
+        $attributeId = 5;
+        $prices = [
+            [
+                'store_id' => 1,
+                'row_id' => 1,
+                'value' => 15
+            ]
+        ];
+        $this->attributeRepository->expects($this->once())->method('get')->willReturn($this->productAttribute);
+        $this->productAttribute->expects($this->once())->method('getAttributeId')->willReturn($attributeId);
+        $this->attributeResource->expects($this->exactly(2))->method('getConnection')->willReturn($this->connection);
+        $this->connection->expects($this->once())->method('beginTransaction')->willReturnSelf();
+        $this->attributeResource
+            ->expects($this->once())
+            ->method('getTable')
+            ->with('catalog_product_entity_decimal')
+            ->willReturn('catalog_product_entity_decimal');
+        $this->connection
+            ->expects($this->once())
+            ->method('insertOnDuplicate')
+            ->with(
+                'catalog_product_entity_decimal',
+                [
+                    [
+                        'store_id' => 1,
+                        'row_id' => 1,
+                        'value' => 15,
+                        'attribute_id' => 5,
+                    ]
+                ],
+                ['value']
+            )
+            ->willReturnSelf();
+        $this->connection->expects($this->once())->method('commit')->willReturnSelf();
+        $this->model->update($prices);
+    }
+
+    /**
+     * Test update method throws exception.
+     *
+     * @expectedException \Magento\Framework\Exception\CouldNotSaveException
+     * @expectedExceptionMessage Could not save Prices.
+     */
+    public function testUpdateWithException()
+    {
+        $attributeId = 5;
+        $prices = [
+            [
+                'store_id' => 1,
+                'row_id' => 1,
+                'value' => 15
+            ]
+        ];
+        $this->attributeRepository->expects($this->once())->method('get')->willReturn($this->productAttribute);
+        $this->productAttribute->expects($this->once())->method('getAttributeId')->willReturn($attributeId);
+        $this->attributeResource->expects($this->exactly(2))->method('getConnection')->willReturn($this->connection);
+        $this->connection->expects($this->once())->method('beginTransaction')->willReturnSelf();
+        $this->attributeResource
+            ->expects($this->once())
+            ->method('getTable')
+            ->with('catalog_product_entity_decimal')
+            ->willReturn('catalog_product_entity_decimal');
+        $this->connection
+            ->expects($this->once())
+            ->method('insertOnDuplicate')
+            ->with(
+                'catalog_product_entity_decimal',
+                [
+                    [
+                        'store_id' => 1,
+                        'row_id' => 1,
+                        'value' => 15,
+                        'attribute_id' => 5,
+                    ]
+                ],
+                ['value']
+            )
+            ->willReturnSelf();
+        $this->connection->expects($this->once())->method('commit')->willThrowException(new \Exception());
+        $this->connection->expects($this->once())->method('rollback')->willReturnSelf();
+        $this->model->update($prices);
+    }
+
+    /**
+     * Test delete method.
+     *
+     * @return void
+     */
+    public function testDelete()
+    {
+        $attributeId = 5;
+        $skus = ['sku_1', 'sku_2'];
+        $idsBySku = [
+            'sku_1' =>
+                [
+                    1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE
+                ],
+            'sku_2' =>
+                [
+                    2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL
+                ]
+        ];
+        $this->productIdLocator
+            ->expects($this->once())
+            ->method('retrieveProductIdsBySkus')->with($skus)
+            ->willReturn($idsBySku);
+        $this->attributeRepository->expects($this->once())->method('get')->willReturn($this->productAttribute);
+        $this->productAttribute->expects($this->once())->method('getAttributeId')->willReturn($attributeId);
+        $this->attributeResource->expects($this->exactly(2))->method('getConnection')->willReturn($this->connection);
+        $this->connection->expects($this->once())->method('beginTransaction')->willReturnSelf();
+        $this->attributeResource
+            ->expects($this->once())
+            ->method('getTable')
+            ->with('catalog_product_entity_decimal')
+            ->willReturn('catalog_product_entity_decimal');
+        $this->connection
+            ->expects($this->once())
+            ->method('delete')
+            ->with(
+                'catalog_product_entity_decimal',
+                [
+                    'attribute_id = ?' => $attributeId,
+                    'row_id IN (?)' => [1, 2]
+                ]
+            )
+            ->willReturnSelf();
+        $this->connection->expects($this->once())->method('commit')->willReturnSelf();
+        $this->metadataPool->expects($this->atLeastOnce())->method('getMetadata')->willReturnSelf();
+        $this->metadataPool->expects($this->atLeastOnce())->method('getLinkField')->willReturn('row_id');
+        $this->model->delete($skus);
+    }
+
+    /**
+     * Test delete method throws exception.
+     *
+     * @expectedException \Magento\Framework\Exception\CouldNotDeleteException
+     * @expectedExceptionMessage Could not delete Prices
+     */
+    public function testDeleteWithException()
+    {
+        $attributeId = 5;
+        $skus = ['sku_1', 'sku_2'];
+        $idsBySku = [
+            'sku_1' =>
+                [
+                    1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE
+                ],
+            'sku_2' =>
+                [
+                    2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL
+                ]
+        ];
+        $this->productIdLocator
+            ->expects($this->once())
+            ->method('retrieveProductIdsBySkus')->with($skus)
+            ->willReturn($idsBySku);
+        $this->attributeRepository->expects($this->once())->method('get')->willReturn($this->productAttribute);
+        $this->productAttribute->expects($this->once())->method('getAttributeId')->willReturn($attributeId);
+        $this->attributeResource->expects($this->exactly(2))->method('getConnection')->willReturn($this->connection);
+        $this->connection->expects($this->once())->method('beginTransaction')->willReturnSelf();
+        $this->attributeResource
+            ->expects($this->once())
+            ->method('getTable')
+            ->with('catalog_product_entity_decimal')
+            ->willReturn('catalog_product_entity_decimal');
+        $this->connection
+            ->expects($this->once())
+            ->method('delete')
+            ->with(
+                'catalog_product_entity_decimal',
+                [
+                    'attribute_id = ?' => $attributeId,
+                    'row_id IN (?)' => [1, 2]
+                ]
+            )
+            ->willReturnSelf();
+        $this->connection->expects($this->once())->method('commit')->willThrowException(new \Exception());
+        $this->connection->expects($this->once())->method('rollBack')->willReturnSelf();
+        $this->metadataPool->expects($this->atLeastOnce())->method('getMetadata')->willReturnSelf();
+        $this->metadataPool->expects($this->atLeastOnce())->method('getLinkField')->willReturn('row_id');
+        $this->model->delete($skus);
+    }
+
+    /**
+     * Test retrieveSkuById method.
+     *
+     * @param int|null $expectedResult
+     * @param int $id
+     * @param array $skus
+     * @dataProvider dataProviderRetrieveSkuById
+     */
+    public function testRetrieveSkuById($expectedResult, $id, array $skus)
+    {
+        $this->productIdLocator
+            ->expects($this->once())
+            ->method('retrieveProductIdsBySkus')
+            ->willReturn($skus);
+
+        $this->assertEquals($expectedResult, $this->model->retrieveSkuById($id, $skus));
+    }
+
+    /**
+     * Data provider for retrieveSkuById  method.
+     *
+     * @return array
+     */
+    public function dataProviderRetrieveSkuById()
+    {
+        return [
+            [
+                null,
+                2,
+                ['sku_1' => [1 => 1]]
+            ],
+            [
+                'sku_1',
+                1,
+                ['sku_1' => [1 => 1]]
+            ],
+            [
+                null,
+                1,
+                ['sku_1' => [2 => 1]]
+            ],
+        ];
+    }
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/TierPriceStorageTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/TierPriceStorageTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2a885dd8b83698bffcb0106992bee076692bffca
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/TierPriceStorageTest.php
@@ -0,0 +1,292 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\Unit\Model\Product\Price;
+
+/**
+ * TierPriceStorage test.
+ */
+class TierPriceStorageTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Product\Price\TierPricePersistence|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $tierPricePersistence;
+
+    /**
+     * @var \Magento\Catalog\Model\Product\Price\TierPriceValidator|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $tierPriceValidator;
+
+    /**
+     * @var \Magento\Catalog\Model\Product\Price\TierPriceFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $tierPriceFactory;
+
+    /**
+     * @var \Magento\Catalog\Model\Indexer\Product\Price|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $priceIndexer;
+
+    /**
+     * @var \Magento\Catalog\Model\ProductIdLocatorInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productIdLocator;
+
+    /**
+     * @var \Magento\PageCache\Model\Config|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $config;
+
+    /**
+     * @var \Magento\Framework\App\Cache\TypeListInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $typeList;
+
+    /**
+     * @var \Magento\Catalog\Model\Product\Price\TierPriceStorage
+     */
+    private $tierPriceStorage;
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function setUp()
+    {
+        $this->tierPricePersistence = $this->getMock(
+            \Magento\Catalog\Model\Product\Price\TierPricePersistence::class,
+            [],
+            [],
+            '',
+            false
+        );
+        $this->tierPricePersistence->expects($this->any())
+            ->method('getEntityLinkField')
+            ->willReturn('row_id');
+        $this->tierPriceValidator = $this->getMock(
+            \Magento\Catalog\Model\Product\Price\TierPriceValidator::class,
+            [],
+            [],
+            '',
+            false
+        );
+        $this->tierPriceFactory = $this->getMock(
+            \Magento\Catalog\Model\Product\Price\TierPriceFactory::class,
+            [],
+            [],
+            '',
+            false
+        );
+        $this->priceIndexer = $this->getMock(
+            \Magento\Catalog\Model\Indexer\Product\Price::class,
+            [],
+            [],
+            '',
+            false
+        );
+        $this->productIdLocator = $this->getMock(
+            \Magento\Catalog\Model\ProductIdLocatorInterface::class,
+            [],
+            [],
+            '',
+            false
+        );
+        $this->config = $this->getMock(
+            \Magento\PageCache\Model\Config::class,
+            [],
+            [],
+            '',
+            false
+        );
+        $this->typeList = $this->getMock(
+            \Magento\Framework\App\Cache\TypeListInterface::class,
+            [],
+            [],
+            '',
+            false
+        );
+        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+        $this->tierPriceStorage = $objectManager->getObject(
+            \Magento\Catalog\Model\Product\Price\TierPriceStorage::class,
+            [
+                'tierPricePersistence' => $this->tierPricePersistence,
+                'tierPriceValidator' => $this->tierPriceValidator,
+                'tierPriceFactory' => $this->tierPriceFactory,
+                'priceIndexer' => $this->priceIndexer,
+                'productIdLocator' => $this->productIdLocator,
+                'config' => $this->config,
+                'typeList' => $this->typeList,
+            ]
+        );
+    }
+
+    /**
+     * Test get method.
+     * @return void
+     */
+    public function testGet()
+    {
+        $skus = ['simple', 'virtual'];
+        $this->productIdLocator->expects($this->atLeastOnce())
+            ->method('retrieveProductIdsBySkus')
+            ->with(['simple', 'virtual'])
+            ->willReturn(['simple' => ['2' => 'simple'], 'virtual' => ['3' => 'virtual']]);
+        $this->tierPricePersistence->expects($this->once())
+            ->method('get')
+            ->willReturn(
+                [
+                    [
+                        'value_id' => 1,
+                        'row_id' => 2,
+                        'all_groups' => 1,
+                        'customer_group_id' => 0,
+                        'qty' => 2.0000,
+                        'value' => 2.0000,
+                        'percentage_value' => null,
+                        'website_id' => 0
+                    ],
+                    [
+                        'value_id' => 2,
+                        'row_id' => 3,
+                        'all_groups' => 1,
+                        'customer_group_id' => 0,
+                        'qty' => 3.0000,
+                        'value' => 3.0000,
+                        'percentage_value' => null,
+                        'website_id' => 0
+                    ]
+                ]
+            );
+        $price = $this->getMockBuilder(\Magento\Catalog\Api\Data\TierPriceInterface::class)->getMockForAbstractClass();
+        $this->tierPriceFactory->expects($this->at(0))->method('create')->willReturn($price);
+        $this->tierPriceFactory->expects($this->at(1))->method('create')->willReturn($price);
+        $prices = $this->tierPriceStorage->get($skus);
+        $this->assertNotEmpty($prices);
+        $this->assertEquals(2, count($prices));
+    }
+
+    /**
+     * Test update method.
+     * @return void
+     */
+    public function testUpdate()
+    {
+        $this->productIdLocator->expects($this->atLeastOnce())
+            ->method('retrieveProductIdsBySkus')
+            ->willReturn(['bundle' => ['2' => 'bundle']]);
+        $this->tierPriceValidator->expects($this->atLeastOnce())->method('validatePrices')->willReturn(true);
+        $this->tierPriceFactory->expects($this->atLeastOnce())->method('createSkeleton')->willReturn(
+            [
+                'row_id' => 2,
+                'all_groups' => 1,
+                'customer_group_id' => 0,
+                'qty' => 2,
+                'value' => 3,
+                'percentage_value' => null,
+                'website_id' => 0
+            ]
+        );
+        $this->tierPricePersistence->expects($this->once())
+            ->method('get')
+            ->willReturn(
+                [
+                    [
+                        'value_id' => 1,
+                        'row_id' => 2,
+                        'all_groups' => 1,
+                        'customer_group_id' => 0,
+                        'qty' => 2.0000,
+                        'value' => 2.0000,
+                        'percentage_value' => null,
+                        'website_id' => 0
+                    ]
+                ]
+            );
+        $this->tierPricePersistence->expects($this->atLeastOnce())->method('update');
+        $this->priceIndexer->expects($this->atLeastOnce())->method('execute');
+        $this->config->expects($this->atLeastOnce())->method('isEnabled')->willReturn(true);
+        $this->typeList->expects($this->atLeastOnce())->method('invalidate');
+        $price = $this->getMockBuilder(\Magento\Catalog\Api\Data\TierPriceInterface::class)->getMockForAbstractClass();
+        $price->method('getSku')->willReturn('bundle');
+        $this->assertTrue($this->tierPriceStorage->update([$price]));
+    }
+
+    /**
+     * Test replace method.
+     * @return void
+     */
+    public function testReplace()
+    {
+        $this->tierPriceValidator->expects($this->atLeastOnce())->method('validatePrices');
+        $this->productIdLocator->expects($this->atLeastOnce())
+            ->method('retrieveProductIdsBySkus')
+            ->willReturn(['virtual' => ['2' => 'virtual']]);
+        $this->tierPriceFactory->expects($this->atLeastOnce())->method('createSkeleton')->willReturn(
+            [
+                'row_id' => 3,
+                'all_groups' => 1,
+                'customer_group_id' => 0,
+                'qty' => 3,
+                'value' => 7,
+                'percentage_value' => null,
+                'website_id' => 0
+            ]
+        );
+        $this->tierPricePersistence->expects($this->atLeastOnce())->method('replace');
+        $this->priceIndexer->expects($this->atLeastOnce())->method('execute');
+        $price = $this->getMockBuilder(\Magento\Catalog\Api\Data\TierPriceInterface::class)->getMockForAbstractClass();
+        $price->method('getSku')->willReturn('virtual');
+        $this->config->expects($this->atLeastOnce())->method('isEnabled')->willReturn(true);
+        $this->typeList->expects($this->atLeastOnce())->method('invalidate');
+        $this->assertTrue($this->tierPriceStorage->replace([$price]));
+    }
+
+    /**
+     * Test delete method.
+     * @return void
+     */
+    public function testDelete()
+    {
+        $this->tierPriceValidator->expects($this->atLeastOnce())->method('validatePrices');
+        $this->productIdLocator->expects($this->atLeastOnce())
+            ->method('retrieveProductIdsBySkus')
+            ->willReturn(['simple' => ['2' => 'simple']]);
+        $this->tierPricePersistence->expects($this->once())
+            ->method('get')
+            ->willReturn(
+                [
+                    [
+                        'value_id' => 7,
+                        'row_id' => 7,
+                        'all_groups' => 1,
+                        'customer_group_id' => 0,
+                        'qty' => 5.0000,
+                        'value' => 6.0000,
+                        'percentage_value' => null,
+                        'website_id' => 0
+                    ]
+                ]
+            );
+        $this->tierPriceFactory->expects($this->atLeastOnce())->method('createSkeleton')->willReturn(
+            [
+                'row_id' => 3,
+                'all_groups' => 1,
+                'customer_group_id' => 0,
+                'qty' => 3,
+                'value' => 7,
+                'percentage_value' => null,
+                'website_id' => 0
+            ]
+        );
+        $this->tierPricePersistence->expects($this->atLeastOnce())->method('delete');
+        $this->priceIndexer->expects($this->atLeastOnce())->method('execute');
+        $this->config->expects($this->atLeastOnce())->method('isEnabled')->willReturn(true);
+        $this->typeList->expects($this->atLeastOnce())->method('invalidate');
+        $price = $this->getMockBuilder(\Magento\Catalog\Api\Data\TierPriceInterface::class)->getMockForAbstractClass();
+        $price->method('getSku')->willReturn('simple');
+        $this->assertTrue($this->tierPriceStorage->delete([$price]));
+    }
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/TierPriceValidatorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/TierPriceValidatorTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1f44c2a75d1862ded128a2c35622dc148e3403a2
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/TierPriceValidatorTest.php
@@ -0,0 +1,471 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\Unit\Model\Product\Price;
+
+use Magento\Catalog\Api\Data\TierPriceInterface;
+
+/**
+ * Class TierPriceValidatorTest.
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class TierPriceValidatorTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\ProductIdLocatorInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productIdLocator;
+
+    /**
+     * @var \Magento\Framework\Api\SearchCriteriaBuilder|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $searchCriteriaBuilder;
+
+    /**
+     * @var \Magento\Framework\Api\FilterBuilder|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $filterBuilder;
+
+    /**
+     * @var \Magento\Customer\Api\GroupRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $customerGroupRepository;
+
+    /**
+     * @var \Magento\Store\Api\WebsiteRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $websiteRepository;
+
+    /**
+     * @var \Magento\Catalog\Model\Product\Price\TierPricePersistence|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $tierPricePersistence;
+
+    /**
+     * @var \Magento\Catalog\Api\Data\TierPriceInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $tierPriceInterface;
+
+    /**
+     * @var \Magento\Catalog\Model\Product\Price\TierPriceValidator
+     */
+    private $model;
+
+    /**
+     * Set up.
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->productIdLocator = $this->getMockForAbstractClass(
+            \Magento\Catalog\Model\ProductIdLocatorInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['retrieveProductIdsBySkus']
+        );
+        $this->searchCriteriaBuilder = $this->getMock(
+            \Magento\Framework\Api\SearchCriteriaBuilder::class,
+            ['addFilters', 'create'],
+            [],
+            '',
+            false
+        );
+        $this->filterBuilder = $this->getMock(
+            \Magento\Framework\Api\FilterBuilder::class,
+            ['setField', 'setValue', 'create'],
+            [],
+            '',
+            false
+        );
+        $this->customerGroupRepository = $this->getMockForAbstractClass(
+            \Magento\Customer\Api\GroupRepositoryInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getList']
+        );
+        $this->websiteRepository = $this->getMockForAbstractClass(
+            \Magento\Store\Api\WebsiteRepositoryInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getById']
+        );
+        $this->tierPricePersistence = $this->getMock(
+            \Magento\Catalog\Model\Product\Price\TierPricePersistence::class,
+            ['addFilters', 'create'],
+            [],
+            '',
+            false
+        );
+        $this->tierPriceInterface = $this->getMockForAbstractClass(
+            \Magento\Catalog\Api\Data\TierPriceInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getSku', 'getPrice', 'getPriceType', 'getQuantity', 'getWebsiteId', 'getCustomerGroup']
+        );
+
+        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+        $this->model = $objectManager->getObject(
+            \Magento\Catalog\Model\Product\Price\TierPriceValidator::class,
+            [
+                'productIdLocator' => $this->productIdLocator,
+                'searchCriteriaBuilder' => $this->searchCriteriaBuilder,
+                'filterBuilder' => $this->filterBuilder,
+                'customerGroupRepository' => $this->customerGroupRepository,
+                'websiteRepository' => $this->websiteRepository,
+                'tierPricePersistence' => $this->tierPricePersistence,
+                'allowedProductTypes' => ['simple', 'virtual', 'bundle', 'downloadable'],
+            ]
+        );
+    }
+
+    /**
+     * Test validateSkus method.
+     *
+     * @return void
+     */
+    public function testValidateSkus()
+    {
+        $skus = ['sku_1', 'sku_2'];
+        $idsBySku = [
+            'sku_1' => [1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE],
+            'sku_2' => [2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL],
+        ];
+        $this->productIdLocator
+            ->expects($this->once())
+            ->method('retrieveProductIdsBySkus')
+            ->with($skus)
+            ->willReturn($idsBySku);
+        $this->model->validateSkus($skus);
+    }
+
+    /**
+     * Test validateSkus method throws exception.
+     *
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     * @expectedExceptionMessage Requested products don't exist: sku_1, sku_2
+     */
+    public function testValidateSkusWithException()
+    {
+        $skus = ['sku_1', 'sku_2'];
+        $idsBySku = [
+            'sku_1' => [1 => 'grouped'],
+            'sku_2' => [2 => 'configurable'],
+        ];
+        $this->productIdLocator
+            ->expects($this->once())
+            ->method('retrieveProductIdsBySkus')
+            ->with($skus)
+            ->willReturn($idsBySku);
+        $this->model->validateSkus($skus);
+    }
+
+    /**
+     * Test validatePrices method.
+     *
+     * @return void
+     */
+    public function testValidatePrices()
+    {
+        $sku = 'sku_1';
+        $idsBySku = [
+            'sku_1' => [1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE],
+            'sku_2' => [2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL],
+        ];
+        $productPrice = 15;
+        $this->tierPriceInterface->expects($this->exactly(8))->method('getSku')->willReturn($sku);
+        $this->productIdLocator->expects($this->exactly(2))->method('retrieveProductIdsBySkus')->willReturn($idsBySku);
+        $this->tierPriceInterface->expects($this->exactly(2))->method('getPrice')->willReturn($productPrice);
+        $this->tierPriceInterface
+            ->expects($this->exactly(2))
+            ->method('getPriceType')
+            ->willReturn(TierPriceInterface::PRICE_TYPE_FIXED);
+        $this->tierPriceInterface->expects($this->exactly(3))->method('getQuantity')->willReturn(2);
+        $this->checkWebsite($this->tierPriceInterface);
+        $this->checkGroup($this->tierPriceInterface);
+        $this->model->validatePrices([$this->tierPriceInterface], []);
+    }
+
+    /**
+     * Test validatePrices method with downloadable product.
+     *
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @expectedExceptionMessage Invalid attribute sku: .
+     */
+    public function testValidatePricesWithDownloadableProduct()
+    {
+        $this->tierPriceInterface->expects($this->exactly(2))->method('getSku')->willReturn(null);
+        $this->model->validatePrices([$this->tierPriceInterface], []);
+    }
+
+    /**
+     * Test validatePrices method with negative price.
+     *
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @expectedExceptionMessage Invalid attribute Price: -15.
+     */
+    public function testValidatePricesWithNegativePrice()
+    {
+        $negativePrice = -15;
+        $sku = 'sku_1';
+        $idsBySku = [
+            'sku_1' => [1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE],
+            'sku_2' => [2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL],
+        ];
+        $this->tierPriceInterface->expects($this->exactly(3))->method('getSku')->willReturn($sku);
+        $this->productIdLocator->expects($this->exactly(2))->method('retrieveProductIdsBySkus')->willReturn($idsBySku);
+        $this->tierPriceInterface->expects($this->exactly(3))->method('getPrice')->willReturn($negativePrice);
+        $this->model->validatePrices([$this->tierPriceInterface], []);
+    }
+
+    /**
+     * Test validatePrices method with bundle product and fixed price.
+     *
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @expectedExceptionMessage Invalid attribute Price Type: fixed.
+     */
+    public function testValidatePricesWithBundleProductAndFixedPrice()
+    {
+        $sku = 'sku_1';
+        $idsBySku = [
+            'sku_1' => [1 => \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE],
+        ];
+        $productPrice = 15;
+        $this->tierPriceInterface->expects($this->exactly(4))->method('getSku')->willReturn($sku);
+        $this->productIdLocator->expects($this->exactly(2))->method('retrieveProductIdsBySkus')->willReturn($idsBySku);
+        $this->tierPriceInterface->expects($this->exactly(2))->method('getPrice')->willReturn($productPrice);
+        $this->tierPriceInterface
+            ->expects($this->exactly(4))
+            ->method('getPriceType')
+            ->willReturn(TierPriceInterface::PRICE_TYPE_FIXED);
+        $this->model->validatePrices([$this->tierPriceInterface], []);
+    }
+
+    /**
+     * Test validatePrices method with zero quantity.
+     *
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @expectedExceptionMessage Invalid attribute Quantity: 0.
+     */
+    public function testValidatePricesWithZeroQty()
+    {
+        $sku = 'sku_1';
+        $idsBySku = [
+            'sku_1' => [1 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL],
+        ];
+        $productPrice = 15;
+        $this->tierPriceInterface->expects($this->exactly(4))->method('getSku')->willReturn($sku);
+        $this->productIdLocator->expects($this->exactly(2))->method('retrieveProductIdsBySkus')->willReturn($idsBySku);
+        $this->tierPriceInterface->expects($this->exactly(2))->method('getPrice')->willReturn($productPrice);
+        $this->tierPriceInterface
+            ->expects($this->exactly(2))
+            ->method('getPriceType')
+            ->willReturn(TierPriceInterface::PRICE_TYPE_FIXED);
+        $this->tierPriceInterface->expects($this->exactly(2))->method('getQuantity')->willReturn(0);
+        $this->model->validatePrices([$this->tierPriceInterface], []);
+    }
+
+    /**
+     * Test validatePrices method without website.
+     *
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @expectedExceptionMessage Invalid attribute website_id: 15.
+     */
+    public function testValidatePricesWithoutWebsite()
+    {
+        $sku = 'sku_1';
+        $idsBySku = [
+            'sku_1' => [1 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL],
+        ];
+        $productPrice = 15;
+        $exception = new \Magento\Framework\Exception\NoSuchEntityException();
+        $this->tierPriceInterface->expects($this->exactly(4))->method('getSku')->willReturn($sku);
+        $this->productIdLocator->expects($this->exactly(2))->method('retrieveProductIdsBySkus')->willReturn($idsBySku);
+        $this->tierPriceInterface->expects($this->exactly(2))->method('getPrice')->willReturn($productPrice);
+        $this->tierPriceInterface
+            ->expects($this->exactly(2))
+            ->method('getPriceType')
+            ->willReturn(TierPriceInterface::PRICE_TYPE_FIXED);
+        $this->tierPriceInterface->expects($this->once())->method('getQuantity')->willReturn(2);
+        $this->websiteRepository->expects($this->once())->method('getById')->willThrowException($exception);
+        $this->tierPriceInterface->expects($this->exactly(2))->method('getWebsiteId')->willReturn(15);
+        $this->model->validatePrices([$this->tierPriceInterface], []);
+    }
+
+    /**
+     * Test validatePrices method not unique.
+     *
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @expectedExceptionMessage We found a duplicate website, tier price, customer
+     * group and quantity: Customer Group = retailer, Website Id = 2, Quantity = 2.
+     */
+    public function testValidatePricesNotUnique()
+    {
+        $sku = 'sku_1';
+        $idsBySku = [
+            'sku_1' => [1 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL],
+        ];
+        $productPrice = 15;
+        $this->tierPriceInterface->expects($this->exactly(8))->method('getSku')->willReturn($sku);
+        $this->productIdLocator->expects($this->exactly(2))->method('retrieveProductIdsBySkus')->willReturn($idsBySku);
+        $this->tierPriceInterface->expects($this->exactly(2))->method('getPrice')->willReturn($productPrice);
+        $this->tierPriceInterface
+            ->expects($this->exactly(2))
+            ->method('getPriceType')
+            ->willReturn(TierPriceInterface::PRICE_TYPE_FIXED);
+        $website = $this->getMockForAbstractClass(
+            \Magento\Store\Api\Data\WebsiteInterface::class,
+            [],
+            '',
+            false
+        );
+        $this->tierPriceInterface
+            ->expects($this->exactly(5))
+            ->method('getWebsiteId')
+            ->willReturnOnConsecutiveCalls(1, 0, 0, 1, 2);
+        $this->websiteRepository->expects($this->once())->method('getById')->willReturn($website);
+        $this->tierPriceInterface->expects($this->exactly(4))->method('getQuantity')->willReturn(2);
+        $this->tierPriceInterface->expects($this->exactly(3))->method('getCustomerGroup')->willReturn('retailer');
+        $this->model->validatePrices([$this->tierPriceInterface], []);
+    }
+
+    /**
+     * Test validatePrices method without group.
+     *
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @expectedExceptionMessage No such entity with Customer Group = wholesale.
+     */
+    public function testValidatePricesWithoutGroup()
+    {
+        $sku = 'sku_1';
+        $idsBySku = [
+            'sku_1' => [1 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL],
+        ];
+        $productPrice = 15;
+        $this->tierPriceInterface->expects($this->exactly(8))->method('getSku')->willReturn($sku);
+        $this->productIdLocator->expects($this->exactly(2))->method('retrieveProductIdsBySkus')->willReturn($idsBySku);
+        $this->tierPriceInterface->expects($this->exactly(2))->method('getPrice')->willReturn($productPrice);
+        $this->tierPriceInterface
+            ->expects($this->exactly(2))
+            ->method('getPriceType')
+            ->willReturn(TierPriceInterface::PRICE_TYPE_FIXED);
+        $this->tierPriceInterface->expects($this->exactly(3))->method('getQuantity')->willReturn(2);
+        $this->checkWebsite($this->tierPriceInterface);
+        $searchCriteria = $this->getMock(
+            \Magento\Framework\Api\SearchCriteria::class,
+            [],
+            [],
+            '',
+            false
+        );
+        $searchResults = $this->getMockForAbstractClass(
+            \Magento\Customer\Api\Data\GroupSearchResultsInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getItems']
+        );
+        $this->tierPriceInterface->expects($this->exactly(3))->method('getCustomerGroup')->willReturn('wholesale');
+        $this->searchCriteriaBuilder->expects($this->once())->method('addFilters')->willReturnSelf();
+        $this->filterBuilder->expects($this->once())->method('setField')->with('customer_group_code')->willReturnSelf();
+        $this->filterBuilder->expects($this->once())->method('setValue')->with('wholesale')->willReturnSelf();
+        $this->filterBuilder->expects($this->once())->method('create')->willReturnSelf();
+        $this->searchCriteriaBuilder
+            ->expects($this->once())
+            ->method('create')
+            ->willReturn($searchCriteria);
+        $this->customerGroupRepository
+            ->expects($this->once())
+            ->method('getList')
+            ->with($searchCriteria)
+            ->willReturn($searchResults);
+        $searchResults->expects($this->once())->method('getItems')->willReturn([]);
+        $this->model->validatePrices([$this->tierPriceInterface], []);
+    }
+
+    /**
+     * Check website.
+     *
+     * @param \PHPUnit_Framework_MockObject_MockObject $price
+     */
+    private function checkWebsite(\PHPUnit_Framework_MockObject_MockObject $price)
+    {
+        $website = $this->getMockForAbstractClass(
+            \Magento\Store\Api\Data\WebsiteInterface::class,
+            [],
+            '',
+            false
+        );
+        $price->expects($this->exactly(3))->method('getWebsiteId')->willReturn(1);
+        $this->websiteRepository->expects($this->once())->method('getById')->willReturn($website);
+    }
+
+    /**
+     * Check group.
+     *
+     * @param \PHPUnit_Framework_MockObject_MockObject $price
+     */
+    private function checkGroup(\PHPUnit_Framework_MockObject_MockObject $price)
+    {
+        $searchCriteria = $this->getMock(
+            \Magento\Framework\Api\SearchCriteria::class,
+            [],
+            [],
+            '',
+            false
+        );
+        $searchResults = $this->getMockForAbstractClass(
+            \Magento\Customer\Api\Data\GroupSearchResultsInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getItems']
+        );
+        $group = $this->getMockForAbstractClass(
+            \Magento\Customer\Api\Data\GroupInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getCode', 'getId']
+        );
+
+        $price->expects($this->exactly(3))->method('getCustomerGroup')->willReturn('wholesale');
+        $this->searchCriteriaBuilder->expects($this->once())->method('addFilters')->willReturnSelf();
+        $this->filterBuilder->expects($this->once())->method('setField')->with('customer_group_code')->willReturnSelf();
+        $this->filterBuilder->expects($this->once())->method('setValue')->with('wholesale')->willReturnSelf();
+        $this->filterBuilder->expects($this->once())->method('create')->willReturnSelf();
+        $this->searchCriteriaBuilder
+            ->expects($this->once())
+            ->method('create')
+            ->willReturn($searchCriteria);
+        $this->customerGroupRepository
+            ->expects($this->once())
+            ->method('getList')
+            ->with($searchCriteria)
+            ->willReturn($searchResults);
+        $searchResults->expects($this->once())->method('getItems')->willReturn([$group]);
+        $group->expects($this->once())->method('getCode')->willReturn('wholesale');
+        $group->expects($this->once())->method('getId')->willReturn(4);
+    }
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductIdLocatorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductIdLocatorTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..75f81195f02e420929edbea8580692c1125752b4
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductIdLocatorTest.php
@@ -0,0 +1,158 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\Unit\Model;
+
+/**
+ * Class ProductIdLocatorTest.
+ */
+class ProductIdLocatorTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\Api\SearchCriteriaBuilder|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $searchCriteriaBuilder;
+
+    /**
+     * @var \Magento\Framework\Api\FilterBuilder|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $filterBuilder;
+
+    /**
+     * @var \Magento\Framework\EntityManager\MetadataPool|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $metadataPool;
+
+    /**
+     * @var \Magento\Catalog\Api\ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productRepository;
+
+    /**
+     * @var \Magento\Catalog\Model\ProductIdLocator
+     */
+    private $model;
+
+    /**
+     * Set up.
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->searchCriteriaBuilder = $this->getMock(
+            \Magento\Framework\Api\SearchCriteriaBuilder::class,
+            ['addFilters', 'create'],
+            [],
+            '',
+            false
+        );
+        $this->filterBuilder = $this->getMock(
+            \Magento\Framework\Api\FilterBuilder::class,
+            ['setField', 'setConditionType', 'setValue', 'create'],
+            [],
+            '',
+            false
+        );
+        $this->metadataPool = $this->getMock(
+            \Magento\Framework\EntityManager\MetadataPool::class,
+            ['getMetadata'],
+            [],
+            '',
+            false
+        );
+        $this->productRepository = $this->getMockForAbstractClass(
+            \Magento\Catalog\Api\ProductRepositoryInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getList']
+        );
+
+        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+        $this->model = $objectManager->getObject(
+            \Magento\Catalog\Model\ProductIdLocator::class,
+            [
+                'searchCriteriaBuilder' => $this->searchCriteriaBuilder,
+                'filterBuilder' => $this->filterBuilder,
+                'metadataPool' => $this->metadataPool,
+                'productRepository' => $this->productRepository,
+            ]
+        );
+    }
+
+    /**
+     * Test retrieve
+     */
+    public function testRetrieveProductIdsBySkus()
+    {
+        $skus = ['sku_1', 'sku_2'];
+        $searchCriteria = $this->getMock(
+            \Magento\Framework\Api\SearchCriteria::class,
+            [],
+            [],
+            '',
+            false
+        );
+        $searchResults = $this->getMockForAbstractClass(
+            \Magento\Catalog\Api\Data\ProductSearchResultsInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getItems']
+        );
+        $product = $this->getMockForAbstractClass(
+            \Magento\Catalog\Api\Data\ProductInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getSku', 'getData', 'getTypeId']
+        );
+        $metaDataInterface = $this->getMockForAbstractClass(
+            \Magento\Framework\EntityManager\EntityMetadataInterface::class,
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getLinkField']
+        );
+        $this->searchCriteriaBuilder->expects($this->once())->method('addFilters')->willReturnSelf();
+        $this->filterBuilder->expects($this->once())->method('setField')->with('sku')->willReturnSelf();
+        $this->filterBuilder->expects($this->once())->method('setConditionType')->with('in')->willReturnSelf();
+        $this->filterBuilder->expects($this->once())->method('setValue')->with(['sku_1', 'sku_2'])->willReturnSelf();
+        $this->filterBuilder->expects($this->once())->method('create')->willReturnSelf();
+        $this->searchCriteriaBuilder
+            ->expects($this->once())
+            ->method('create')
+            ->willReturn($searchCriteria);
+        $this->productRepository
+            ->expects($this->once())
+            ->method('getList')
+            ->with($searchCriteria)
+            ->willReturn($searchResults);
+        $searchResults->expects($this->once())->method('getItems')->willReturn([$product]);
+        $this->metadataPool
+            ->expects($this->once())
+            ->method('getMetadata')
+            ->with(\Magento\Catalog\Api\Data\ProductInterface::class)
+            ->willReturn($metaDataInterface);
+        $metaDataInterface->expects($this->once())->method('getLinkField')->willReturn('entity_id');
+        $product->expects($this->once())->method('getSku')->willReturn('sku_1');
+        $product->expects($this->once())->method('getData')->with('entity_id')->willReturn(1);
+        $product->expects($this->once())->method('getTypeId')->willReturn('simple');
+        $this->assertEquals(
+            ['sku_1' => [1 => 'simple']],
+            $this->model->retrieveProductIdsBySkus($skus)
+        );
+    }
+}
diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php
index 53360de08b434b4a0314fe341760c55fef476ef4..326e92417670a77bc269625153f3a56f715bb7e5 100644
--- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php
+++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php
@@ -407,6 +407,7 @@ class AdvancedPricing extends AbstractModifier
                 'data' => [
                     'config' => [
                         'componentType' => 'dynamicRows',
+                        'component' => 'Magento_Catalog/js/components/dynamic-rows-tier-price',
                         'label' => __('Customer Group Price'),
                         'renderDefaultRecord' => false,
                         'recordTemplate' => 'record',
diff --git a/app/code/Magento/Catalog/etc/adminhtml/di.xml b/app/code/Magento/Catalog/etc/adminhtml/di.xml
index 5fc5ec8d44fd0a88f8a5d542d5518fa60ad77629..d6ecaa7c40391de2b12abac33d25b9ecd5620af8 100644
--- a/app/code/Magento/Catalog/etc/adminhtml/di.xml
+++ b/app/code/Magento/Catalog/etc/adminhtml/di.xml
@@ -169,4 +169,9 @@
             <argument name="scopeName" xsi:type="string">product_form.product_form</argument>
         </arguments>
     </type>
+    <type name="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\TierPrice">
+        <arguments>
+            <argument name="productPriceOptions" xsi:type="object">Magento\Catalog\Model\Config\Source\Product\Options\TierPrice</argument>
+        </arguments>
+    </type>
 </config>
diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml
index 27b9a19065e99f22fccf4f2f42076c69d0f1e0c2..0142f7c2f261837ae1e0d8f25418486951da3043 100644
--- a/app/code/Magento/Catalog/etc/di.xml
+++ b/app/code/Magento/Catalog/etc/di.xml
@@ -51,6 +51,13 @@
     <preference for="Magento\Catalog\Model\Product\Pricing\Renderer\SalableResolverInterface" type="Magento\Catalog\Model\Product\Pricing\Renderer\SalableResolver"/>
     <preference for="Magento\Catalog\Model\Product\Media\ConfigInterface" type="Magento\Catalog\Model\Product\Media\Config"/>
     <preference for="Magento\Framework\View\Asset\ContextInterface" type="Magento\Catalog\Model\View\Asset\Image\Context"/>
+    <preference for="Magento\Catalog\Api\TierPriceStorageInterface" type="Magento\Catalog\Model\Product\Price\TierPriceStorage" />
+    <preference for="Magento\Catalog\Api\Data\TierPriceInterface" type="Magento\Catalog\Model\Product\Price\TierPrice" />
+    <preference for="Magento\Catalog\Api\BasePriceStorageInterface" type="Magento\Catalog\Model\Product\Price\BasePriceStorage" />
+    <preference for="Magento\Catalog\Api\Data\BasePriceInterface" type="Magento\Catalog\Model\Product\Price\BasePrice" />
+    <preference for="Magento\Catalog\Api\CostStorageInterface" type="Magento\Catalog\Model\Product\Price\CostStorage" />
+    <preference for="Magento\Catalog\Api\Data\CostInterface" type="Magento\Catalog\Model\Product\Price\Cost" />
+    <preference for="Magento\Catalog\Model\ProductIdLocatorInterface" type="Magento\Catalog\Model\ProductIdLocator" />
     <type name="Magento\Customer\Model\ResourceModel\Visitor">
         <plugin name="catalogLog" type="Magento\Catalog\Model\Plugin\Log" />
     </type>
@@ -848,4 +855,30 @@
             </argument>
         </arguments>
     </type>
+    <type name="Magento\Catalog\Model\Product\Price\CostStorage">
+        <arguments>
+            <argument name="allowedProductTypes" xsi:type="array">
+                <item name="0" xsi:type="string">simple</item>
+                <item name="1" xsi:type="string">virtual</item>
+            </argument>
+        </arguments>
+    </type>
+    <type name="Magento\Catalog\Model\Product\Price\BasePriceStorage">
+        <arguments>
+            <argument name="allowedProductTypes" xsi:type="array">
+                <item name="0" xsi:type="string">simple</item>
+                <item name="1" xsi:type="string">virtual</item>
+                <item name="2" xsi:type="string">bundle</item>
+            </argument>
+        </arguments>
+    </type>
+    <type name="Magento\Catalog\Model\Product\Price\TierPriceValidator">
+        <arguments>
+            <argument name="allowedProductTypes" xsi:type="array">
+                <item name="0" xsi:type="string">simple</item>
+                <item name="1" xsi:type="string">virtual</item>
+                <item name="2" xsi:type="string">bundle</item>
+            </argument>
+        </arguments>
+    </type>
 </config>
diff --git a/app/code/Magento/Catalog/etc/webapi.xml b/app/code/Magento/Catalog/etc/webapi.xml
index 99670c347a89babc45714d5ed0350676f5cf48fe..b53f11b1ff2959a583b1a401a7566ca7eee33589 100644
--- a/app/code/Magento/Catalog/etc/webapi.xml
+++ b/app/code/Magento/Catalog/etc/webapi.xml
@@ -246,6 +246,60 @@
             <resource ref="Magento_Catalog::catalog"/>
         </resources>
     </route>
+    <route url="/V1/products/tier-prices-information" method="POST">
+        <service class="Magento\Catalog\Api\TierPriceStorageInterface" method="get"/>
+        <resources>
+            <resource ref="Magento_Catalog::catalog"/>
+        </resources>
+    </route>
+    <route url="/V1/products/tier-prices" method="POST">
+        <service class="Magento\Catalog\Api\TierPriceStorageInterface" method="update"/>
+        <resources>
+            <resource ref="Magento_Catalog::catalog"/>
+        </resources>
+    </route>
+    <route url="/V1/products/tier-prices" method="PUT">
+        <service class="Magento\Catalog\Api\TierPriceStorageInterface" method="replace"/>
+        <resources>
+            <resource ref="Magento_Catalog::catalog"/>
+        </resources>
+    </route>
+    <route url="/V1/products/tier-prices-delete" method="POST">
+        <service class="Magento\Catalog\Api\TierPriceStorageInterface" method="delete"/>
+        <resources>
+            <resource ref="Magento_Catalog::catalog"/>
+        </resources>
+    </route>
+    <route url="/V1/products/base-prices-information" method="POST">
+        <service class="Magento\Catalog\Api\BasePriceStorageInterface" method="get"/>
+        <resources>
+            <resource ref="Magento_Catalog::catalog"/>
+        </resources>
+    </route>
+    <route url="/V1/products/base-prices" method="POST">
+        <service class="Magento\Catalog\Api\BasePriceStorageInterface" method="update"/>
+        <resources>
+            <resource ref="Magento_Catalog::catalog"/>
+        </resources>
+    </route>
+    <route url="/V1/products/cost-information" method="POST">
+        <service class="Magento\Catalog\Api\CostStorageInterface" method="get"/>
+        <resources>
+            <resource ref="Magento_Catalog::catalog"/>
+        </resources>
+    </route>
+    <route url="/V1/products/cost" method="POST">
+        <service class="Magento\Catalog\Api\CostStorageInterface" method="update"/>
+        <resources>
+            <resource ref="Magento_Catalog::catalog"/>
+        </resources>
+    </route>
+    <route url="/V1/products/cost-delete" method="POST">
+        <service class="Magento\Catalog\Api\CostStorageInterface" method="delete"/>
+        <resources>
+            <resource ref="Magento_Catalog::catalog"/>
+        </resources>
+    </route>
 
     <route url="/V1/categories/:categoryId" method="DELETE">
         <service class="Magento\Catalog\Api\CategoryRepositoryInterface" method="deleteByIdentifier" />
diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/dynamic-rows-tier-price.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/dynamic-rows-tier-price.js
new file mode 100644
index 0000000000000000000000000000000000000000..6dc4c747a44514be814ea4d939135070287052d8
--- /dev/null
+++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/dynamic-rows-tier-price.js
@@ -0,0 +1,29 @@
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+define([
+    'underscore',
+    'Magento_Ui/js/dynamic-rows/dynamic-rows'
+], function (_, DynamicRows) {
+    'use strict';
+
+    return DynamicRows.extend({
+
+        /**
+         * Init header elements
+         */
+        initHeader: function () {
+            var labels;
+
+            this._super();
+            labels = _.clone(this.labels());
+            labels = _.sortBy(labels, function (label) {
+                return label.sortOrder;
+            });
+
+            this.labels(labels);
+        }
+    });
+});
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php
index 08e75ceebecc6160825bc12b0380a03b4a1af0ab..337134c9453c01dad20e4581e4d82019aa956b6d 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php
@@ -6,11 +6,16 @@
 namespace Magento\CatalogSearch\Model\Indexer;
 
 use Magento\CatalogSearch\Model\Indexer\Fulltext\Action\FullFactory;
+use Magento\CatalogSearch\Model\Indexer\Scope\State;
 use Magento\CatalogSearch\Model\ResourceModel\Fulltext as FulltextResource;
-use \Magento\Framework\Search\Request\Config as SearchRequestConfig;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Search\Request\Config as SearchRequestConfig;
 use Magento\Framework\Search\Request\DimensionFactory;
 use Magento\Store\Model\StoreManagerInterface;
 
+/**
+ * Provide functionality for Fulltext Search indexing
+ */
 class Fulltext implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
 {
     /**
@@ -18,34 +23,51 @@ class Fulltext implements \Magento\Framework\Indexer\ActionInterface, \Magento\F
      */
     const INDEXER_ID = 'catalogsearch_fulltext';
 
-    /** @var array index structure */
+    /**
+     * @var array index structure
+     */
     protected $data;
 
     /**
      * @var IndexerHandlerFactory
      */
     private $indexerHandlerFactory;
+
     /**
      * @var StoreManagerInterface
      */
     private $storeManager;
+
     /**
-     * @var DimensionFactory
+     * @var \Magento\Framework\Search\Request\DimensionFactory
      */
     private $dimensionFactory;
+
     /**
-     * @var Full
+     * @var \Magento\CatalogSearch\Model\Indexer\Fulltext\Action\Full
      */
     private $fullAction;
+
     /**
      * @var FulltextResource
      */
     private $fulltextResource;
+
     /**
-     * @var SearchRequestConfig
+     * @var \Magento\Framework\Search\Request\Config
      */
     private $searchRequestConfig;
 
+    /**
+     * @var IndexSwitcherInterface
+     */
+    private $indexSwitcher;
+
+    /**
+     * @var \Magento\CatalogSearch\Model\Indexer\Scope\State
+     */
+    private $indexScopeState;
+
     /**
      * @param FullFactory $fullActionFactory
      * @param IndexerHandlerFactory $indexerHandlerFactory
@@ -54,6 +76,8 @@ class Fulltext implements \Magento\Framework\Indexer\ActionInterface, \Magento\F
      * @param FulltextResource $fulltextResource
      * @param SearchRequestConfig $searchRequestConfig
      * @param array $data
+     * @param IndexSwitcherInterface $indexSwitcher
+     * @param Scope\State $indexScopeState
      */
     public function __construct(
         FullFactory $fullActionFactory,
@@ -62,7 +86,9 @@ class Fulltext implements \Magento\Framework\Indexer\ActionInterface, \Magento\F
         DimensionFactory $dimensionFactory,
         FulltextResource $fulltextResource,
         SearchRequestConfig $searchRequestConfig,
-        array $data
+        array $data,
+        IndexSwitcherInterface $indexSwitcher = null,
+        State $indexScopeState = null
     ) {
         $this->fullAction = $fullActionFactory->create(['data' => $data]);
         $this->indexerHandlerFactory = $indexerHandlerFactory;
@@ -71,6 +97,14 @@ class Fulltext implements \Magento\Framework\Indexer\ActionInterface, \Magento\F
         $this->fulltextResource = $fulltextResource;
         $this->searchRequestConfig = $searchRequestConfig;
         $this->data = $data;
+        if (null === $indexSwitcher) {
+            $indexSwitcher = ObjectManager::getInstance()->get(IndexSwitcherInterface::class);
+        }
+        if (null === $indexScopeState) {
+            $indexScopeState = ObjectManager::getInstance()->get(State::class);
+        }
+        $this->indexSwitcher = $indexSwitcher;
+        $this->indexScopeState = $indexScopeState;
     }
 
     /**
@@ -106,10 +140,14 @@ class Fulltext implements \Magento\Framework\Indexer\ActionInterface, \Magento\F
             'data' => $this->data
         ]);
         foreach ($storeIds as $storeId) {
-            $dimension = $this->dimensionFactory->create(['name' => 'scope', 'value' => $storeId]);
-            $saveHandler->cleanIndex([$dimension]);
-            $saveHandler->saveIndex([$dimension], $this->fullAction->rebuildStoreIndex($storeId));
+            $dimensions = [$this->dimensionFactory->create(['name' => 'scope', 'value' => $storeId])];
+            $this->indexScopeState->useTemporaryIndex();
+
+            $saveHandler->cleanIndex($dimensions);
+            $saveHandler->saveIndex($dimensions, $this->fullAction->rebuildStoreIndex($storeId));
 
+            $this->indexSwitcher->switchIndex($dimensions);
+            $this->indexScopeState->useRegularIndex();
         }
         $this->fulltextResource->resetSearchResults();
         $this->searchRequestConfig->reset();
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructure.php b/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructure.php
index 9a2bb76c04ce76ccfa60e757c2075120ef2d09e2..d2d76bc71ccbf4223036f59e8eebc65fcbd94c4c 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructure.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructure.php
@@ -12,6 +12,7 @@ use Magento\Framework\DB\Ddl\Table;
 use Magento\Framework\Search\Request\Dimension;
 use Magento\Framework\Indexer\IndexStructureInterface;
 use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver;
+use Magento\Framework\Search\Request\IndexScopeResolverInterface;
 
 class IndexStructure implements IndexStructureInterface
 {
@@ -19,6 +20,7 @@ class IndexStructure implements IndexStructureInterface
      * @var Resource
      */
     private $resource;
+
     /**
      * @var IndexScopeResolver
      */
@@ -26,11 +28,11 @@ class IndexStructure implements IndexStructureInterface
 
     /**
      * @param ResourceConnection $resource
-     * @param IndexScopeResolver $indexScopeResolver
+     * @param IndexScopeResolverInterface $indexScopeResolver
      */
     public function __construct(
         ResourceConnection $resource,
-        IndexScopeResolver $indexScopeResolver
+        IndexScopeResolverInterface $indexScopeResolver
     ) {
         $this->resource = $resource;
         $this->indexScopeResolver = $indexScopeResolver;
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/IndexSwitcherInterface.php b/app/code/Magento/CatalogSearch/Model/Indexer/IndexSwitcherInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..ba5fb461dde35aa0a6cdfebc1520b8d1091d841b
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/IndexSwitcherInterface.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\CatalogSearch\Model\Indexer;
+
+/**
+ * Provides a functionality to replace main index with its temporary representation
+ */
+interface IndexSwitcherInterface
+{
+    /**
+     * Switch current index with temporary index
+     *
+     * It will drop current index table and rename temporary index table to the current index table.
+     *
+     * @param array $dimensions
+     * @return void
+     */
+    public function switchIndex(array $dimensions);
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/IndexSwitcherProxy.php b/app/code/Magento/CatalogSearch/Model/Indexer/IndexSwitcherProxy.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ce093ed99e3a48aebadc2a02c788fd9de018591
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/IndexSwitcherProxy.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Model\Indexer;
+
+use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Framework\ObjectManagerInterface;
+use Magento\Store\Model\ScopeInterface;
+
+/**
+ * Proxy for adapter-specific index switcher
+ */
+class IndexSwitcherProxy implements IndexSwitcherInterface
+{
+    /**
+     * Object Manager instance
+     *
+     * @var ObjectManagerInterface
+     */
+    private $objectManager = null;
+
+    /**
+     * Instance name to create
+     *
+     * @var string
+     */
+    private $handlers;
+
+    /**
+     * @var ScopeConfigInterface
+     */
+    private $scopeConfig;
+
+    /**
+     * Configuration path by which current indexer handler stored
+     *
+     * @var string
+     */
+    private $configPath;
+
+    /**
+     * Factory constructor
+     *
+     * @param ObjectManagerInterface $objectManager
+     * @param ScopeConfigInterface $scopeConfig
+     * @param string $configPath
+     * @param string[] $handlers
+     */
+    public function __construct(
+        ObjectManagerInterface $objectManager,
+        ScopeConfigInterface $scopeConfig,
+        $configPath,
+        array $handlers = []
+    ) {
+        $this->objectManager = $objectManager;
+        $this->scopeConfig = $scopeConfig;
+        $this->configPath = $configPath;
+        $this->handlers = $handlers;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * As index switcher is an optional part of the search SPI, it may be not defined by a search engine.
+     * It is especially reasonable for search engines with pre-defined indexes declaration (like old SOLR and Sphinx)
+     * which cannot create temporary indexes on the fly.
+     * That's the reason why this method do nothing for the case
+     * when switcher is not defined for a specific search engine.
+     */
+    public function switchIndex(array $dimensions)
+    {
+        $currentHandler = $this->scopeConfig->getValue($this->configPath, ScopeInterface::SCOPE_STORE);
+        if (!isset($this->handlers[$currentHandler])) {
+            return;
+        }
+        $this->create($currentHandler)->switchIndex($dimensions);
+    }
+
+    /**
+     * Create indexer handler
+     *
+     * @param string $handler
+     * @return IndexSwitcherInterface
+     */
+    private function create($handler)
+    {
+        $indexSwitcher = $this->objectManager->create($this->handlers[$handler]);
+
+        if (!$indexSwitcher instanceof IndexSwitcherInterface) {
+            throw new \InvalidArgumentException(
+                $handler . ' index switcher doesn\'t implement ' . IndexSwitcherInterface::class
+            );
+        }
+
+        return $indexSwitcher;
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php b/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php
index 8d99cd4492bf59cd4c98439cc402ec36d93744f6..2aa9a418bd7258f9046ebdf889f7b69f8a0c8d31 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php
@@ -7,13 +7,11 @@ namespace Magento\CatalogSearch\Model\Indexer;
 
 use Magento\Eav\Model\Config;
 use Magento\Framework\App\ResourceConnection;
-use Magento\Framework\DB\Adapter\AdapterInterface;
 use Magento\Framework\Indexer\SaveHandler\IndexerInterface;
 use Magento\Framework\Indexer\IndexStructureInterface;
 use Magento\Framework\Search\Request\Dimension;
 use Magento\Framework\Search\Request\IndexScopeResolverInterface;
 use Magento\Framework\Indexer\SaveHandler\Batch;
-use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver;
 
 class IndexerHandler implements IndexerInterface
 {
@@ -62,7 +60,7 @@ class IndexerHandler implements IndexerInterface
      * @param ResourceConnection $resource
      * @param Config $eavConfig
      * @param Batch $batch
-     * @param \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver $indexScopeResolver
+     * @param IndexScopeResolverInterface $indexScopeResolver
      * @param array $data
      * @param int $batchSize
      */
@@ -71,7 +69,7 @@ class IndexerHandler implements IndexerInterface
         ResourceConnection $resource,
         Config $eavConfig,
         Batch $batch,
-        IndexScopeResolver $indexScopeResolver,
+        IndexScopeResolverInterface $indexScopeResolver,
         array $data,
         $batchSize = 100
     ) {
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Scope/IndexSwitcher.php b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/IndexSwitcher.php
new file mode 100644
index 0000000000000000000000000000000000000000..87a7b7110d3aae24999040e62d75bdd01052528e
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/IndexSwitcher.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\CatalogSearch\Model\Indexer\Scope;
+
+use Magento\CatalogSearch\Model\Indexer\IndexSwitcherInterface;
+use Magento\Framework\App\ResourceConnection;
+use Magento\Framework\Search\Request\IndexScopeResolverInterface;
+
+/**
+ * Provides a functionality to replace main index with its temporary representation
+ */
+class IndexSwitcher implements IndexSwitcherInterface
+{
+    /**
+     * @var Resource
+     */
+    private $resource;
+
+    /**
+     * @var ScopeProxy
+     */
+    private $resolver;
+
+    /**
+     * @var State
+     */
+    private $state;
+
+    /**
+     * @param ResourceConnection $resource
+     * @param IndexScopeResolverInterface $indexScopeResolver
+     * @param State $state
+     */
+    public function __construct(
+        ResourceConnection $resource,
+        IndexScopeResolverInterface $indexScopeResolver,
+        State $state
+    ) {
+        $this->resource = $resource;
+        $this->resolver = $indexScopeResolver;
+        $this->state = $state;
+    }
+
+    /**
+     * {@inheritdoc}
+     * @throws IndexTableNotExistException
+     */
+    public function switchIndex(array $dimensions)
+    {
+        if (State::USE_TEMPORARY_INDEX === $this->state->getState()) {
+            $index = \Magento\CatalogSearch\Model\Indexer\Fulltext::INDEXER_ID;
+
+            $temporalIndexTable = $this->resolver->resolve($index, $dimensions);
+            if (!$this->resource->getConnection()->isTableExists($temporalIndexTable)) {
+                throw new IndexTableNotExistException(
+                    __(
+                        "Temporary table for index $index doesn't exist,"
+                        . " which is inconsistent with state of scope resolver"
+                    )
+                );
+            }
+
+            $this->state->useRegularIndex();
+            $tableName = $this->resolver->resolve($index, $dimensions);
+            if ($this->resource->getConnection()->isTableExists($tableName)) {
+                $this->resource->getConnection()->dropTable($tableName);
+            }
+
+            $this->resource->getConnection()->renameTable($temporalIndexTable, $tableName);
+            $this->state->useTemporaryIndex();
+        }
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Scope/IndexTableNotExistException.php b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/IndexTableNotExistException.php
new file mode 100644
index 0000000000000000000000000000000000000000..6974f8c278ab55af0cb41f501124eb3201f5e914
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/IndexTableNotExistException.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Model\Indexer\Scope;
+
+
+use Magento\Framework\Exception\LocalizedException;
+
+/**
+ * Exception which represents situation where temporary index table should be used somewhere,
+ * but it does not exist in a database
+ */
+class IndexTableNotExistException extends LocalizedException
+{
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Scope/ScopeProxy.php b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/ScopeProxy.php
new file mode 100644
index 0000000000000000000000000000000000000000..14832af303bf4167df380776f28de09482c84e7f
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/ScopeProxy.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Model\Indexer\Scope;
+
+
+use Magento\Framework\Search\Request\Dimension;
+
+/**
+ * Implementation of IndexScopeResolverInterface which resolves index scope dynamically
+ * depending on current scope state
+ */
+class ScopeProxy implements \Magento\Framework\Search\Request\IndexScopeResolverInterface
+{
+    /**
+     * Object Manager instance
+     *
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    private $objectManager;
+
+    /**
+     * @var array
+     */
+    private $states = [];
+
+    /**
+     * @var State
+     */
+    private $scopeState;
+
+    /**
+     * Factory constructor
+     *
+     * @param \Magento\Framework\ObjectManagerInterface $objectManager
+     * @param State $scopeState
+     * @param array $states
+     */
+    public function __construct(
+        \Magento\Framework\ObjectManagerInterface $objectManager,
+        State $scopeState,
+        array $states
+    ) {
+        $this->objectManager = $objectManager;
+        $this->scopeState = $scopeState;
+        $this->states = $states;
+    }
+
+    /**
+     * Creates class instance with specified parameters
+     *
+     * @param string $state
+     * @return \Magento\Framework\Search\Request\IndexScopeResolverInterface
+     * @throws UnknownStateException
+     */
+    private function create($state)
+    {
+        if (!array_key_exists($state, $this->states)) {
+            throw new UnknownStateException(__("Requested resolver for unknown indexer state: $state"));
+        }
+        return $this->objectManager->create($this->states[$state]);
+    }
+
+    /**
+     * @param string $index
+     * @param Dimension[] $dimensions
+     * @return string
+     */
+    public function resolve($index, array $dimensions)
+    {
+        return $this->create($this->scopeState->getState())->resolve($index, $dimensions);
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Scope/State.php b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/State.php
new file mode 100644
index 0000000000000000000000000000000000000000..2bba29ae8d842f963146bef411d3a71023740ae8
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/State.php
@@ -0,0 +1,65 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Model\Indexer\Scope;
+
+
+use Magento\Framework\App\ResourceConnection;
+use Magento\Framework\App\ScopeResolverInterface;
+use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver;
+use Magento\Framework\Search\Request\Dimension;
+use Magento\Framework\Search\Request\IndexScopeResolverInterface;
+
+/**
+ * This class represents state that defines which table should be used during indexation process
+ *
+ * There are two possible states:
+ *   - use_temporary_table
+ *   - use_main_table
+ *
+ * The 'use_main_table' state means that default indexer table should be used.
+ *
+ * The 'use_temporary_table' state is an opposite for 'use_main_table'
+ *   which means that default indexer table should be left unchanged during indexation
+ *   and temporary table should be used instead.
+ *
+ */
+class State
+{
+    const USE_TEMPORARY_INDEX = 'use_temporary_table';
+    const USE_REGULAR_INDEX = 'use_main_table';
+
+    /**
+     * @var string
+     */
+    private $state = self::USE_REGULAR_INDEX;
+
+    /**
+     * Set the state to use temporary Index
+     * @return void
+     */
+    public function useTemporaryIndex()
+    {
+        $this->state = self::USE_TEMPORARY_INDEX;
+    }
+
+    /**
+     * Set the state to use regular Index
+     * @return void
+     */
+    public function useRegularIndex()
+    {
+        $this->state = self::USE_REGULAR_INDEX;
+    }
+
+    /**
+     * @return string
+     */
+    public function getState()
+    {
+        return $this->state;
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Scope/TemporaryResolver.php b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/TemporaryResolver.php
new file mode 100644
index 0000000000000000000000000000000000000000..51037eb637cf3c346fdcd7ac64aefc0a50e14949
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/TemporaryResolver.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Model\Indexer\Scope;
+
+
+use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver;
+use Magento\Framework\Search\Request\Dimension;
+
+/**
+ * Resolves name of a temporary table for indexation
+ */
+class TemporaryResolver implements \Magento\Framework\Search\Request\IndexScopeResolverInterface
+{
+    /**
+     * @var IndexScopeResolver
+     */
+    private $indexScopeResolver;
+
+    /**
+     * @inheritDoc
+     */
+    public function __construct(IndexScopeResolver $indexScopeResolver)
+    {
+        $this->indexScopeResolver = $indexScopeResolver;
+    }
+
+    /**
+     * @param string $index
+     * @param Dimension[] $dimensions
+     * @return string
+     */
+    public function resolve($index, array $dimensions)
+    {
+        $tableName = $this->indexScopeResolver->resolve($index, $dimensions);
+        $tableName .= \Magento\Framework\Indexer\Table\StrategyInterface::TMP_SUFFIX;
+
+        return $tableName;
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Scope/UnknownStateException.php b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/UnknownStateException.php
new file mode 100644
index 0000000000000000000000000000000000000000..04803ef27480efd504949ecc43773ebd3db3d2f3
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/UnknownStateException.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Model\Indexer\Scope;
+
+
+use Magento\Framework\Exception\LocalizedException;
+
+/**
+ * Exception for situation where used state which is not defined in configuration
+ */
+class UnknownStateException extends LocalizedException
+{
+
+}
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/FulltextTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/FulltextTest.php
index f4c0437590ed56c72c5e0076f79be93d181e082c..6ef656d566867dec02cf3a157e1b6d0c3cd24826 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/FulltextTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/FulltextTest.php
@@ -8,7 +8,13 @@ namespace Magento\CatalogSearch\Test\Unit\Model\Indexer;
 use Magento\CatalogSearch\Model\ResourceModel\Fulltext as FulltextResource;
 use Magento\Framework\Search\Request\Config as SearchRequestConfig;
 use Magento\Framework\Search\Request\DimensionFactory;
+use Magento\Framework\Search\Request\Dimension;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+use \Magento\CatalogSearch\Model\Indexer\Fulltext\IndexSwitcher;
 
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
 class FulltextTest extends \PHPUnit_Framework_TestCase
 {
     /**
@@ -26,11 +32,6 @@ class FulltextTest extends \PHPUnit_Framework_TestCase
      */
     protected $storeManager;
 
-    /**
-     * @var \Magento\Framework\Search\Request\Dimension|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $dimension;
-
     /**
      * @var \Magento\CatalogSearch\Model\Indexer\IndexerHandler|\PHPUnit_Framework_MockObject_MockObject
      */
@@ -47,8 +48,15 @@ class FulltextTest extends \PHPUnit_Framework_TestCase
     protected $searchRequestConfig;
 
     /**
-     *
+     * @var \Magento\Framework\Search\Request\DimensionFactory|\PHPUnit_Framework_MockObject_MockObject
      */
+    private $dimensionFactory;
+
+    /**
+     * @var \Magento\CatalogSearch\Model\Indexer\Scope\IndexSwitcher|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $indexSwitcher;
+
     protected function setUp()
     {
         $this->fullAction = $this->getClassMock(\Magento\CatalogSearch\Model\Indexer\Fulltext\Action\Full::class);
@@ -80,27 +88,29 @@ class FulltextTest extends \PHPUnit_Framework_TestCase
             []
         );
 
-        $this->dimension = $this->getClassMock(\Magento\Framework\Search\Request\Dimension::class);
-        $dimensionFactory = $this->getMock(
-            \Magento\Framework\Search\Request\DimensionFactory::class,
-            ['create'],
-            [],
-            '',
-            false
-        );
-        $dimensionFactory->expects($this->any())->method('create')->willReturn($this->dimension);
+        $this->dimensionFactory = $this->getMock(DimensionFactory::class, ['create'], [], '', false);
 
         $this->fulltextResource = $this->getClassMock(\Magento\CatalogSearch\Model\ResourceModel\Fulltext::class);
         $this->searchRequestConfig = $this->getClassMock(\Magento\Framework\Search\Request\Config::class);
 
-        $this->model = new \Magento\CatalogSearch\Model\Indexer\Fulltext(
-            $fullActionFactory,
-            $indexerHandlerFactory,
-            $this->storeManager,
-            $dimensionFactory,
-            $this->fulltextResource,
-            $this->searchRequestConfig,
-            []
+        $this->indexSwitcher = $this->getMockBuilder(\Magento\CatalogSearch\Model\Indexer\Scope\IndexSwitcher::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['switchIndex'])
+            ->getMock();
+
+        $objectManagerHelper = new ObjectManagerHelper($this);
+        $this->model = $objectManagerHelper->getObject(
+            \Magento\CatalogSearch\Model\Indexer\Fulltext::class,
+            [
+                'fullActionFactory' => $fullActionFactory,
+                'indexerHandlerFactory' => $indexerHandlerFactory,
+                'storeManager' => $this->storeManager,
+                'dimensionFactory' => $this->dimensionFactory,
+                'fulltextResource' => $this->fulltextResource,
+                'searchRequestConfig' => $this->searchRequestConfig,
+                'data' => [],
+                'indexSwitcher' => $this->indexSwitcher,
+            ]
         );
     }
 
@@ -131,13 +141,38 @@ class FulltextTest extends \PHPUnit_Framework_TestCase
     public function testExecuteFull()
     {
         $stores = [0 => 'Store 1', 1 => 'Store 2'];
-        $indexData = new \ArrayObject([]);
+        $indexData = new \ArrayObject([new \ArrayObject([]), new \ArrayObject([])]);
         $this->storeManager->expects($this->once())->method('getStores')->willReturn($stores);
-        $this->saveHandler->expects($this->exactly(count($stores)))->method('cleanIndex');
-        $this->saveHandler->expects($this->exactly(2))->method('saveIndex');
+
+        $dimensionScope1 = $this->getMock(Dimension::class, [], ['scope', '1']);
+        $dimensionScope2 = $this->getMock(Dimension::class, [], ['scope', '2']);
+
+        $this->dimensionFactory->expects($this->any())->method('create')->willReturnOnConsecutiveCalls(
+            $dimensionScope1,
+            $dimensionScope2
+        );
+        $this->indexSwitcher->expects($this->exactly(2))->method('switchIndex')
+            ->withConsecutive(
+                [$this->equalTo([$dimensionScope1])],
+                [$this->equalTo([$dimensionScope2])]
+            );
+
+        $this->saveHandler->expects($this->exactly(count($stores)))->method('cleanIndex')
+            ->withConsecutive(
+                [$this->equalTo([$dimensionScope1])],
+                [$this->equalTo([$dimensionScope2])]
+            );
+
+        $this->saveHandler->expects($this->exactly(2))->method('saveIndex')
+            ->withConsecutive(
+                [$this->equalTo([$dimensionScope1]), $this->equalTo($indexData)],
+                [$this->equalTo([$dimensionScope2]), $this->equalTo($indexData)]
+            );
         $this->fullAction->expects($this->exactly(2))
             ->method('rebuildStoreIndex')
-            ->willReturn(new \ArrayObject([$indexData, $indexData]));
+            ->withConsecutive([0], [1])
+            ->willReturn($indexData);
+
         $this->fulltextResource->expects($this->once())->method('resetSearchResults');
         $this->searchRequestConfig->expects($this->once())->method('reset');
 
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Scope/IndexSwitcherTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Scope/IndexSwitcherTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..31bec5906ae5a37c34f666af0999b1cafe2f0485
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Scope/IndexSwitcherTest.php
@@ -0,0 +1,212 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\CatalogSearch\Test\Unit\Model\Indexer\Scope;
+
+use Magento\CatalogSearch\Model\Indexer\Scope\IndexSwitcher;
+use Magento\CatalogSearch\Model\Indexer\Scope\State;
+use Magento\Framework\App\ResourceConnection;
+use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver;
+use Magento\Framework\Indexer\IndexStructureInterface;
+use Magento\Framework\Search\Request\Dimension;
+use Magento\CatalogSearch\Model\Indexer\Fulltext as FulltextIndexer;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+
+class IndexSwitcherTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\DB\Adapter\AdapterInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $connection;
+
+    /**
+     * @var \Magento\Framework\Search\Request\IndexScopeResolverInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $indexScopeResolver;
+
+    /**
+     * @var State|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $scopeState;
+
+    /**
+     * @var IndexSwitcher
+     */
+    private $indexSwitcher;
+
+    /**
+     * @var ResourceConnection|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $resource;
+
+    protected function setUp()
+    {
+        $this->resource = $this->getMockBuilder(ResourceConnection::class)
+            ->setMethods(['getConnection'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->connection = $this->getMockBuilder(\Magento\Framework\DB\Adapter\AdapterInterface::class)
+            ->setMethods(['isTableExists', 'dropTable', 'renameTable'])
+            ->getMockForAbstractClass();
+        $this->resource->expects($this->any())
+            ->method('getConnection')
+            ->willReturn($this->connection);
+        $this->indexScopeResolver = $this->getMockBuilder(
+            \Magento\Framework\Search\Request\IndexScopeResolverInterface::class
+        )
+            ->setMethods(['resolve'])
+            ->getMockForAbstractClass();
+        $this->scopeState = $this->getMockBuilder(State::class)
+            ->setMethods(['getState', 'useRegularIndex', 'useTemporaryIndex'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $objectManagerHelper = new ObjectManagerHelper($this);
+        $this->indexSwitcher = $objectManagerHelper->getObject(
+            \Magento\CatalogSearch\Model\Indexer\Scope\IndexSwitcher::class,
+            [
+                'resource' => $this->resource,
+                'indexScopeResolver' => $this->indexScopeResolver,
+                'state' => $this->scopeState,
+            ]
+        );
+    }
+
+    public function testSwitchRegularIndex()
+    {
+        $dimensions = [$this->getMockBuilder(Dimension::class)->setConstructorArgs(['scope', '1'])];
+
+        $this->scopeState->expects($this->once())
+            ->method('getState')
+            ->willReturn(State::USE_REGULAR_INDEX);
+
+        $this->indexScopeResolver->expects($this->never())->method('resolve');
+        $this->connection->expects($this->never())->method('renameTable');
+
+        $this->indexSwitcher->switchIndex($dimensions);
+    }
+
+    public function testSwitchIndexWithUnknownState()
+    {
+        $dimensions = [$this->getMockBuilder(Dimension::class)->setConstructorArgs(['scope', '1'])];
+
+        $this->scopeState->expects($this->once())
+            ->method('getState')
+            ->willReturn('unknown_state');
+
+        $this->indexScopeResolver->expects($this->never())->method('resolve');
+        $this->connection->expects($this->never())->method('renameTable');
+
+        $this->indexSwitcher->switchIndex($dimensions);
+    }
+
+    public function testSwitchTemporaryIndexWhenRegularIndexExist()
+    {
+        $dimensions = [$this->getMockBuilder(Dimension::class)->setConstructorArgs(['scope', '1'])];
+
+        $this->scopeState->expects($this->once())
+            ->method('getState')
+            ->willReturn(State::USE_TEMPORARY_INDEX);
+
+        $this->scopeState->expects($this->at(1))->method('useRegularIndex');
+        $this->scopeState->expects($this->at(2))->method('useTemporaryIndex');
+
+        $this->indexScopeResolver->expects($this->exactly(2))->method('resolve')
+            ->withConsecutive(
+                [$this->equalTo(FulltextIndexer::INDEXER_ID), $this->equalTo($dimensions)],
+                [$this->equalTo(FulltextIndexer::INDEXER_ID), $this->equalTo($dimensions)]
+            )
+            ->willReturnOnConsecutiveCalls(
+                'catalogsearch_fulltext_scope1_tmp1',
+                'catalogsearch_fulltext_scope1'
+            );
+
+        $this->connection->expects($this->exactly(2))->method('isTableExists')
+            ->withConsecutive(
+                [$this->equalTo('catalogsearch_fulltext_scope1_tmp1'), $this->equalTo(null)],
+                [$this->equalTo('catalogsearch_fulltext_scope1'), $this->equalTo(null)]
+            )
+            ->willReturnOnConsecutiveCalls(
+                true,
+                true
+            );
+
+        $this->connection->expects($this->once())->method('dropTable')->with('catalogsearch_fulltext_scope1', null);
+        $this->connection->expects($this->once())
+            ->method('renameTable')
+            ->with('catalogsearch_fulltext_scope1_tmp1', 'catalogsearch_fulltext_scope1');
+
+        $this->indexSwitcher->switchIndex($dimensions);
+    }
+
+    public function testSwitchTemporaryIndexWhenRegularIndexNotExist()
+    {
+        $dimensions = [$this->getMockBuilder(Dimension::class)->setConstructorArgs(['scope', '1'])];
+
+        $this->scopeState->expects($this->once())
+            ->method('getState')
+            ->willReturn(State::USE_TEMPORARY_INDEX);
+
+        $this->scopeState->expects($this->at(1))->method('useRegularIndex');
+        $this->scopeState->expects($this->at(2))->method('useTemporaryIndex');
+
+        $this->indexScopeResolver->expects($this->exactly(2))->method('resolve')
+            ->withConsecutive(
+                [$this->equalTo(FulltextIndexer::INDEXER_ID), $this->equalTo($dimensions)],
+                [$this->equalTo(FulltextIndexer::INDEXER_ID), $this->equalTo($dimensions)]
+            )
+            ->willReturnOnConsecutiveCalls(
+                'catalogsearch_fulltext_scope1_tmp1',
+                'catalogsearch_fulltext_scope1'
+            );
+
+        $this->connection->expects($this->exactly(2))->method('isTableExists')
+            ->withConsecutive(
+                [$this->equalTo('catalogsearch_fulltext_scope1_tmp1'), $this->equalTo(null)],
+                [$this->equalTo('catalogsearch_fulltext_scope1'), $this->equalTo(null)]
+            )
+            ->willReturnOnConsecutiveCalls(
+                true,
+                false
+            );
+
+        $this->connection->expects($this->never())->method('dropTable')->with('catalogsearch_fulltext_scope1', null);
+        $this->connection->expects($this->once())
+            ->method('renameTable')
+            ->with('catalogsearch_fulltext_scope1_tmp1', 'catalogsearch_fulltext_scope1');
+
+        $this->indexSwitcher->switchIndex($dimensions);
+    }
+
+    /**
+     * @expectedException \Magento\CatalogSearch\Model\Indexer\Scope\IndexTableNotExistException
+     * @expectedExceptionMessage Temporary table for index catalogsearch_fulltext doesn't exist
+     */
+    public function testSwitchWhenTemporaryIndexNotExist()
+    {
+        $dimensions = [$this->getMockBuilder(Dimension::class)->setConstructorArgs(['scope', '1'])];
+
+        $this->scopeState->expects($this->once())
+            ->method('getState')
+            ->willReturn(State::USE_TEMPORARY_INDEX);
+
+        $this->scopeState->expects($this->never())->method('useRegularIndex');
+        $this->scopeState->expects($this->never())->method('useTemporaryIndex');
+
+        $this->indexScopeResolver->expects($this->once())->method('resolve')
+            ->with(FulltextIndexer::INDEXER_ID, $dimensions)
+            ->willReturn('catalogsearch_fulltext_scope1_tmp1');
+
+        $this->connection->expects($this->once())
+            ->method('isTableExists')
+            ->with('catalogsearch_fulltext_scope1_tmp1', null)
+            ->willReturn(false);
+
+        $this->connection->expects($this->never())->method('dropTable')->with('catalogsearch_fulltext_scope1', null);
+        $this->connection->expects($this->never())->method('renameTable');
+
+        $this->indexSwitcher->switchIndex($dimensions);
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php
index 4b04e7d66ab569ab3d2e6219cef4e2b69268d8e0..d44fef54683fc9e3c91c79d8844c2d620c750079 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php
@@ -74,7 +74,10 @@ class CollectionTest extends BaseCollectionTest
         $productLimitationMock = $this->getMock(
             \Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class
         );
-        $productLimitationFactoryMock = $this->getMock(ProductLimitationFactory::class, ['create']);
+        $productLimitationFactoryMock = $this->getMockBuilder(ProductLimitationFactory::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
         $productLimitationFactoryMock->method('create')
             ->willReturn($productLimitationMock);
 
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php
index 5e56a253563592a55b80b00d26432028d9f4c5fa..5732ed2c8aee1dfa2429757a9e8f67b1cc324f1f 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php
@@ -80,7 +80,10 @@ class CollectionTest extends BaseCollectionTest
         $productLimitationMock = $this->getMock(
             \Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class
         );
-        $productLimitationFactoryMock = $this->getMock(ProductLimitationFactory::class, ['create']);
+        $productLimitationFactoryMock = $this->getMockBuilder(ProductLimitationFactory::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
         $productLimitationFactoryMock->method('create')
             ->willReturn($productLimitationMock);
 
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/Indexer/IndexStructureTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/Indexer/IndexStructureTest.php
index 3bb270e990617d3a9e05ca574e788f5bb3f714aa..8f4bb7736cd37b9bf86d5591e792edea8909ef19 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/Indexer/IndexStructureTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/Indexer/IndexStructureTest.php
@@ -48,9 +48,8 @@ class IndexStructureTest extends \PHPUnit_Framework_TestCase
             ->method('getConnection')
             ->willReturn($this->connection);
         $this->indexScopeResolver = $this->getMockBuilder(
-            \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver::class
+            \Magento\Framework\Search\Request\IndexScopeResolverInterface::class
         )->setMethods(['resolve'])
-            ->disableOriginalConstructor()
             ->getMock();
 
         $objectManager = new ObjectManager($this);
@@ -64,11 +63,6 @@ class IndexStructureTest extends \PHPUnit_Framework_TestCase
         );
     }
 
-    /**
-     * @param string $table
-     * @param array $dimensions
-     * @param bool $isTableExist
-     */
     public function testDelete()
     {
         $index = 'index_name';
diff --git a/app/code/Magento/CatalogSearch/etc/di.xml b/app/code/Magento/CatalogSearch/etc/di.xml
index 7e9451f9b83e7ada30455509b8fd686a0c251705..7116abf263b0dde081a0a7f42f585e807e47ee85 100644
--- a/app/code/Magento/CatalogSearch/etc/di.xml
+++ b/app/code/Magento/CatalogSearch/etc/di.xml
@@ -12,6 +12,7 @@
     <preference for="Magento\Framework\Search\Dynamic\DataProviderInterface" type="Magento\CatalogSearch\Model\Adapter\Mysql\Dynamic\DataProvider" />
     <preference for="Magento\Framework\Search\Adapter\OptionsInterface" type="Magento\CatalogSearch\Model\Adapter\Options" />
     <preference for="Magento\CatalogSearch\Model\Search\FilterMapper\FilterStrategyInterface" type="Magento\CatalogSearch\Model\Search\FilterMapper\FilterContext"/>
+    <preference for="\Magento\CatalogSearch\Model\Indexer\IndexSwitcherInterface" type="\Magento\CatalogSearch\Model\Indexer\IndexSwitcherProxy"/>
     <type name="Magento\CatalogSearch\Model\Indexer\IndexerHandlerFactory">
         <arguments>
             <argument name="configPath" xsi:type="const">Magento\CatalogSearch\Model\ResourceModel\EngineInterface::CONFIG_ENGINE_PATH</argument>
@@ -20,6 +21,14 @@
             </argument>
         </arguments>
     </type>
+    <type name="Magento\CatalogSearch\Model\Indexer\IndexSwitcherProxy">
+        <arguments>
+            <argument name="configPath" xsi:type="const">Magento\CatalogSearch\Model\ResourceModel\EngineInterface::CONFIG_ENGINE_PATH</argument>
+            <argument name="handlers" xsi:type="array">
+                <item name="mysql" xsi:type="string">\Magento\CatalogSearch\Model\Indexer\Scope\IndexSwitcher</item>
+            </argument>
+        </arguments>
+    </type>
     <type name="Magento\CatalogSearch\Model\Indexer\IndexStructureFactory">
         <arguments>
             <argument name="configPath" xsi:type="const">Magento\CatalogSearch\Model\ResourceModel\EngineInterface::CONFIG_ENGINE_PATH</argument>
@@ -246,4 +255,27 @@
             </argument>
         </arguments>
     </type>
+    <type name="\Magento\CatalogSearch\Model\Indexer\IndexerHandler">
+        <arguments>
+            <argument name="indexScopeResolver" xsi:type="object">\Magento\CatalogSearch\Model\Indexer\Scope\ScopeProxy</argument>
+        </arguments>
+    </type>
+    <type name="\Magento\CatalogSearch\Model\Indexer\IndexStructure">
+        <arguments>
+            <argument name="indexScopeResolver" xsi:type="object">\Magento\CatalogSearch\Model\Indexer\Scope\ScopeProxy</argument>
+        </arguments>
+    </type>
+    <type name="\Magento\CatalogSearch\Model\Indexer\Scope\IndexSwitcher">
+        <arguments>
+            <argument name="indexScopeResolver" xsi:type="object">\Magento\CatalogSearch\Model\Indexer\Scope\ScopeProxy</argument>
+        </arguments>
+    </type>
+    <type name="\Magento\CatalogSearch\Model\Indexer\Scope\ScopeProxy">
+        <arguments>
+            <argument name="states" xsi:type="array">
+                <item name="use_temporary_table" xsi:type="string">\Magento\CatalogSearch\Model\Indexer\Scope\TemporaryResolver</item>
+                <item name="use_main_table" xsi:type="string">\Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver</item>
+            </argument>
+        </arguments>
+    </type>
 </config>
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js
index fb15e47eaf7d487da1c8671c545f0b99ce2a7445..78bd0ca73c495785f981a6d2d6ef8e4957fe6d9b 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js
@@ -242,7 +242,7 @@ define(
                     emailValidationResult = customer.isLoggedIn();
 
                 if (!quote.shippingMethod()) {
-                    this.errorValidationMessage($.mage.__('Please specify a shipping method.'));
+                    this.errorValidationMessage($t('Please specify a shipping method.'));
 
                     return false;
                 }
diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php
index 6f2b989e5e9bfaa9fa91643b1958be6a99c0fdc1..794034b446f72b3e1649352f74b74b49345c7a3f 100644
--- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php
+++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php
@@ -29,18 +29,25 @@ class Configurable extends \Magento\CatalogInventory\Model\ResourceModel\Indexer
         $connection = $this->getConnection();
         $idxTable = $usePrimaryTable ? $this->getMainTable() : $this->getIdxTable();
         $select = parent::_getStockStatusSelect($entityIds, $usePrimaryTable);
+        $linkField = $metadata->getLinkField();
         $select->reset(
             \Magento\Framework\DB\Select::COLUMNS
         )->columns(
             ['e.entity_id', 'cis.website_id', 'cis.stock_id']
         )->joinLeft(
             ['l' => $this->getTable('catalog_product_super_link')],
-            'l.parent_id = e.' . $metadata->getLinkField(),
+            'l.parent_id = e.' . $linkField,
             []
         )->join(
             ['le' => $this->getTable('catalog_product_entity')],
             'le.entity_id = l.product_id',
             []
+        )->joinInner(
+            ['cpei' => $this->getTable('catalog_product_entity_int')],
+            'le.' . $linkField . ' = cpei.' . $linkField
+            . ' AND cpei.attribute_id = ' . $this->_getAttribute('status')->getId()
+            . ' AND cpei.value = ' . ProductStatus::STATUS_ENABLED,
+            []
         )->joinLeft(
             ['i' => $idxTable],
             'i.product_id = l.product_id AND cis.website_id = i.website_id AND cis.stock_id = i.stock_id',
diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js
index c182d9f8216c09a42868eb487dfa06b0e718b5c7..be44c110c2b6259484066ffc4c7cbe4400c68d9e 100644
--- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js
+++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js
@@ -32,6 +32,7 @@ define([
             identificationProperty: 'id',
             'attribute_set_id': '',
             attributesTmp: [],
+            changedFlag: 'was_changed',
             listens: {
                 'insertDataFromGrid': 'processingInsertDataFromGrid',
                 'insertDataFromWizard': 'processingInsertDataFromWizard',
@@ -391,9 +392,9 @@ define([
                     'small_image': row['small_image'],
                     image: row.image,
                     'thumbnail': row.thumbnail,
-                    'attributes': attributesText,
-                    'was_changed': true
+                    'attributes': attributesText
                 };
+                product[this.changedFlag] = true;
                 product[this.canEditField] = row.editable;
                 product[this.newProductField] = row.newProduct;
                 tmpArray.push(product);
@@ -515,6 +516,7 @@ define([
                 tmpArray[rowIndex].status = 1;
             }
 
+            tmpArray[rowIndex][this.changedFlag] = true;
             this.unionInsertData(tmpArray);
         }
     });
diff --git a/app/code/Magento/Customer/Model/Indexer/Source.php b/app/code/Magento/Customer/Model/Indexer/Source.php
new file mode 100644
index 0000000000000000000000000000000000000000..60522227eb222fb058c3ddb36681a6276d635e94
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Indexer/Source.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model\Indexer;
+
+use Magento\Customer\Model\ResourceModel\Customer\Indexer\Collection;
+use Magento\Framework\App\ResourceConnection\SourceProviderInterface;
+use Traversable;
+
+/**
+ * Customers data batch generator for customer_grid indexer
+ */
+class Source implements \IteratorAggregate, \Countable, SourceProviderInterface
+{
+    /**
+     * @var Collection
+     */
+    private $customerCollection;
+
+    /**
+     * @var int
+     */
+    private $batchSize;
+
+    /**
+     * @param \Magento\Customer\Model\ResourceModel\Customer\Indexer\CollectionFactory $collection
+     * @param int $batchSize
+     */
+    public function __construct(
+        \Magento\Customer\Model\ResourceModel\Customer\Indexer\CollectionFactory $collectionFactory,
+        $batchSize = 10000
+    ) {
+        $this->customerCollection = $collectionFactory->create();
+        $this->batchSize = $batchSize;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getMainTable()
+    {
+        return $this->customerCollection->getMainTable();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getIdFieldName()
+    {
+        return $this->customerCollection->getIdFieldName();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function addFieldToSelect($fieldName, $alias = null)
+    {
+        $this->customerCollection->addFieldToSelect($fieldName, $alias);
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getSelect()
+    {
+        return $this->customerCollection->getSelect();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function addFieldToFilter($attribute, $condition = null)
+    {
+        $this->customerCollection->addFieldToFilter($attribute, $condition);
+        return $this;
+    }
+
+    /**
+     * @return int
+     */
+    public function count()
+    {
+        return $this->customerCollection->getSize();
+    }
+
+    /**
+     * Retrieve an iterator
+     *
+     * @return Traversable
+     */
+    public function getIterator()
+    {
+        $this->customerCollection->setPageSize($this->batchSize);
+        $lastPage = $this->customerCollection->getLastPageNumber();
+        $pageNumber = 0;
+        do {
+            $this->customerCollection->clear();
+            $this->customerCollection->setCurPage($pageNumber);
+            foreach ($this->customerCollection->getItems() as $key => $value) {
+                yield $key => $value;
+            }
+            $pageNumber++;
+        } while ($pageNumber <= $lastPage);
+    }
+}
diff --git a/app/code/Magento/Customer/Model/ResourceModel/Customer/Indexer/Collection.php b/app/code/Magento/Customer/Model/ResourceModel/Customer/Indexer/Collection.php
new file mode 100644
index 0000000000000000000000000000000000000000..5b9716af5393adb9b91de1579533b6369283d795
--- /dev/null
+++ b/app/code/Magento/Customer/Model/ResourceModel/Customer/Indexer/Collection.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model\ResourceModel\Customer\Indexer;
+
+/**
+ * Customers collection for customer_grid indexer
+ */
+class Collection extends \Magento\Customer\Model\ResourceModel\Customer\Collection
+{
+    /**
+     * @inheritdoc
+     */
+    protected function beforeAddLoadedItem(\Magento\Framework\DataObject $item)
+    {
+        return $item;
+    }
+}
diff --git a/app/code/Magento/Customer/Setup/UpgradeSchema.php b/app/code/Magento/Customer/Setup/UpgradeSchema.php
index 33ec2352e865d0b6fd5cbbde5d9646b5dd92975d..46ccd83fcaae11b3ab4720e5ead60b3625bbda38 100755
--- a/app/code/Magento/Customer/Setup/UpgradeSchema.php
+++ b/app/code/Magento/Customer/Setup/UpgradeSchema.php
@@ -136,14 +136,12 @@ class UpgradeSchema implements UpgradeSchemaInterface
             ]
         );
         foreach ($keys as $key) {
-            $setup->getConnection()->modifyColumn(
+            $description = $setup->getConnection()->describeTable($key['TABLE_NAME'])[$key['COLUMN_NAME']];
+            $description['DATA_TYPE'] = 'int';
+            $setup->getConnection()->modifyColumnByDdl(
                 $key['TABLE_NAME'],
                 $key['COLUMN_NAME'],
-                [
-                    'type' => 'integer',
-                    'unsigned' => true,
-                    'nullable' => false
-                ]
+                $description
             );
         }
     }
diff --git a/app/code/Magento/Customer/etc/indexer.xml b/app/code/Magento/Customer/etc/indexer.xml
index b48592cafbb20b6b62ae2e4fd953ecce1e35e0af..5f644426d81696c643324365ee7e2cacd8fb64cb 100644
--- a/app/code/Magento/Customer/etc/indexer.xml
+++ b/app/code/Magento/Customer/etc/indexer.xml
@@ -11,7 +11,7 @@
         <title translate="true">Customer Grid</title>
         <description translate="true">Rebuild Customer grid index</description>
 
-        <fieldset name="customer" source="Magento\Customer\Model\ResourceModel\Customer\Collection"
+        <fieldset name="customer" source="Magento\Customer\Model\Indexer\Source"
                   provider="Magento\Customer\Model\Indexer\AttributeProvider">
             <field name="name" xsi:type="searchable" dataType="text" handler="CustomerNameHandler"/>
             <field name="email" xsi:type="searchable" dataType="varchar"/>
diff --git a/app/code/Magento/Customer/view/frontend/web/js/view/authentication-popup.js b/app/code/Magento/Customer/view/frontend/web/js/view/authentication-popup.js
index 649238a81d1f714cf6f6ac282b2695dec0a36fbf..0dca72ade73b69a4c7603e31286a68162809976f 100644
--- a/app/code/Magento/Customer/view/frontend/web/js/view/authentication-popup.js
+++ b/app/code/Magento/Customer/view/frontend/web/js/view/authentication-popup.js
@@ -69,19 +69,24 @@ define(
             },
 
             /** Provide login action */
-            login: function (loginForm) {
+            login: function (formUiElement, event) {
                 var loginData = {},
-                    formDataArray = $(loginForm).serializeArray();
+                    formElement = $(event.currentTarget),
+                    formDataArray = formElement.serializeArray();
+
+                event.stopPropagation();
                 formDataArray.forEach(function (entry) {
                     loginData[entry.name] = entry.value;
                 });
 
-                if ($(loginForm).validation() &&
-                    $(loginForm).validation('isValid')
+                if (formElement.validation() &&
+                    formElement.validation('isValid')
                 ) {
                     this.isLoading(true);
-                    loginAction(loginData, null, false);
+                    loginAction(loginData);
                 }
+
+                return false;
             }
         });
     }
diff --git a/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html b/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html
index 9ad2cf5265043b4fd1850514258d99276d500ff3..db9c0a3819ffdbaf09b4cfb4ea1d4385909160d9 100644
--- a/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html
+++ b/app/code/Magento/Customer/view/frontend/web/template/authentication-popup.html
@@ -50,7 +50,7 @@
         <div class="block-content" aria-labelledby="block-customer-login-heading">
             <form class="form form-login"
                   method="post"
-                  data-bind="submit:login"
+                  data-bind="event: {submit: login }"
                   id="login-form">
                 <div class="fieldset login" data-bind="attr: {'data-hasrequired': $t('* Required Fields')}">
                     <div class="field email required">
diff --git a/app/code/Magento/Downloadable/etc/di.xml b/app/code/Magento/Downloadable/etc/di.xml
index d7e2aafe79582d0f50a419cdc9bcf7f2f090cdcd..8e3d0bb6c5c5ae598a8365770f7e2ae932c78d73 100644
--- a/app/code/Magento/Downloadable/etc/di.xml
+++ b/app/code/Magento/Downloadable/etc/di.xml
@@ -123,4 +123,25 @@
             </argument>
         </arguments>
     </type>
+    <type name="Magento\Catalog\Model\Product\Price\CostStorage">
+        <arguments>
+            <argument name="allowedProductTypes" xsi:type="array">
+                <item name="2" xsi:type="string">downloadable</item>
+            </argument>
+        </arguments>
+    </type>
+    <type name="Magento\Catalog\Model\Product\Price\TierPriceValidator">
+        <arguments>
+            <argument name="allowedProductTypes" xsi:type="array">
+                <item name="3" xsi:type="string">downloadable</item>
+            </argument>
+        </arguments>
+    </type>
+    <type name="Magento\Catalog\Model\Product\Price\BasePriceStorage">
+        <arguments>
+            <argument name="allowedProductTypes" xsi:type="array">
+                <item name="3" xsi:type="string">downloadable</item>
+            </argument>
+        </arguments>
+    </type>
 </config>
diff --git a/app/code/Magento/Paypal/Model/Express/Checkout.php b/app/code/Magento/Paypal/Model/Express/Checkout.php
index 0f96b14124d042e86adbad3e944b2bdc97ee2e1a..893eda8cc6020882763056e78f844ab19166c1a6 100644
--- a/app/code/Magento/Paypal/Model/Express/Checkout.php
+++ b/app/code/Magento/Paypal/Model/Express/Checkout.php
@@ -7,7 +7,9 @@ namespace Magento\Paypal\Model\Express;
 
 use Magento\Customer\Api\Data\CustomerInterface as CustomerDataObject;
 use Magento\Customer\Model\AccountManagement;
+use Magento\Framework\App\ObjectManager;
 use Magento\Paypal\Model\Config as PaypalConfig;
+use Magento\Sales\Api\OrderRepositoryInterface;
 use Magento\Sales\Model\Order\Email\Sender\OrderSender;
 use Magento\Quote\Model\Quote\Address;
 use Magento\Framework\DataObject;
@@ -268,6 +270,11 @@ class Checkout
      */
     protected $totalsCollector;
 
+    /**
+     * @var OrderRepositoryInterface
+     */
+    private $orderRepository;
+
     /**
      * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Customer\Model\Url $customerUrl
@@ -789,7 +796,8 @@ class Checkout
 
         $this->ignoreAddressValidation();
         $this->_quote->collectTotals();
-        $order = $this->quoteManagement->submit($this->_quote);
+        $orderId = $this->quoteManagement->placeOrder($this->_quote->getId());
+        $order = $this->getOrderRepository()->get($orderId);
 
         if (!$order) {
             return;
@@ -1157,4 +1165,20 @@ class Checkout
             ->setCustomerGroupId(\Magento\Customer\Model\Group::NOT_LOGGED_IN_ID);
         return $this;
     }
+
+    /**
+     * Returns order repository instance
+     *
+     * @return OrderRepositoryInterface
+     * @deprecated
+     */
+    private function getOrderRepository()
+    {
+        if ($this->orderRepository === null) {
+            $this->orderRepository = ObjectManager::getInstance()
+                ->get(OrderRepositoryInterface::class);
+        }
+
+        return $this->orderRepository;
+    }
 }
diff --git a/app/code/Magento/SalesInventory/composer.json b/app/code/Magento/SalesInventory/composer.json
index fa06db402a286f5f37b2b1991d2c8c49665bd1d8..07bbc9aeba4827a9fa0f78025c647932d0ca6910 100644
--- a/app/code/Magento/SalesInventory/composer.json
+++ b/app/code/Magento/SalesInventory/composer.json
@@ -10,7 +10,7 @@
         "magento/framework": "100.2.*"
     },
     "type": "magento2-module",
-    "version": "100.0.0-dev",
+    "version": "100.2.0-dev",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Search/Controller/Adminhtml/Term/ExportSearchCsv.php b/app/code/Magento/Search/Controller/Adminhtml/Term/ExportSearchCsv.php
index 0d1de5cf80cc3463a8c24f3c36a61b4b40286d94..6b13fbc24953292a01326a819aeb8e325711eba2 100644
--- a/app/code/Magento/Search/Controller/Adminhtml/Term/ExportSearchCsv.php
+++ b/app/code/Magento/Search/Controller/Adminhtml/Term/ExportSearchCsv.php
@@ -40,6 +40,6 @@ class ExportSearchCsv extends TermController
         /** @var \Magento\Framework\View\Result\Layout $resultLayout */
         $resultLayout = $this->resultFactory->create(ResultFactory::TYPE_LAYOUT);
         $content = $resultLayout->getLayout()->getChildBlock('adminhtml.report.search.grid', 'grid.export');
-        return $this->fileFactory->create(\search.csv::class, $content->getCsvFile(), DirectoryList::VAR_DIR);
+        return $this->fileFactory->create('search.csv', $content->getCsvFile(), DirectoryList::VAR_DIR);
     }
 }
diff --git a/app/code/Magento/Search/Test/Unit/Controller/Adminhtml/Term/ExportSearchCsvTest.php b/app/code/Magento/Search/Test/Unit/Controller/Adminhtml/Term/ExportSearchCsvTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..041d14899d5b683693175399cf2836d7b56209b1
--- /dev/null
+++ b/app/code/Magento/Search/Test/Unit/Controller/Adminhtml/Term/ExportSearchCsvTest.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Search\Test\Unit\Controller\Adminhtml\Term;
+
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+use Magento\Framework\Controller\ResultFactory;
+use Magento\Framework\App\Filesystem\DirectoryList;
+
+class ExportSearchCsvTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\TaxImportExport\Controller\Adminhtml\Rate\ExportPost
+     */
+    private $controller;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $fileFactoryMock;
+
+    /**
+     * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
+     */
+    private $objectManagerHelper;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $resultFactoryMock;
+
+    protected function setUp()
+    {
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->fileFactoryMock = $this->getMock(
+            \Magento\Framework\App\Response\Http\FileFactory::class,
+            [],
+            [],
+            '',
+            false
+        );
+        $this->resultFactoryMock = $this->getMock(
+            \Magento\Framework\Controller\ResultFactory::class,
+            [],
+            [],
+            '',
+            false
+        );
+
+        $this->controller = $this->objectManagerHelper->getObject(
+            \Magento\Search\Controller\Adminhtml\Term\ExportSearchCsv::class,
+            [
+                'fileFactory' => $this->fileFactoryMock,
+                'resultFactory' => $this->resultFactoryMock
+            ]
+        );
+    }
+
+    public function testExecute()
+    {
+        $resultLayoutMock = $this->getMock(\Magento\Framework\View\Result\Layout::class, [], [], '', false);
+        $layoutMock = $this->getMock(\Magento\Framework\View\LayoutInterface::class);
+        $contentMock = $this->getMock(
+            \Magento\Framework\View\Element\AbstractBlock::class,
+            ['getCsvFile'],
+            [],
+            '',
+            false
+        );
+        $this->resultFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with(ResultFactory::TYPE_LAYOUT)->willReturn($resultLayoutMock);
+        $resultLayoutMock->expects($this->once())->method('getLayout')->willReturn($layoutMock);
+        $layoutMock->expects($this->once())->method('getChildBlock')->willReturn($contentMock);
+        $contentMock->expects($this->once())->method('getCsvFile')->willReturn('csvFile');
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with('search.csv', 'csvFile', DirectoryList::VAR_DIR);
+        $this->controller->execute();
+    }
+}
diff --git a/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportPost.php b/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportPost.php
index cceb0c6de9fd63b4cf773ad778a27967bad8033d..351a2fe50d46a3b178be6514acbb9244ed2f53ad 100644
--- a/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportPost.php
+++ b/app/code/Magento/TaxImportExport/Controller/Adminhtml/Rate/ExportPost.php
@@ -81,7 +81,7 @@ class ExportPost extends \Magento\TaxImportExport\Controller\Adminhtml\Rate
 
             $content .= $rate->toString($template) . "\n";
         }
-        return $this->fileFactory->create(\tax_rates.csv::class, $content, DirectoryList::VAR_DIR);
+        return $this->fileFactory->create('tax_rates.csv', $content, DirectoryList::VAR_DIR);
     }
 
     /**
diff --git a/app/code/Magento/TaxImportExport/Test/Unit/Controller/Adminhtml/Rate/ExportPostTest.php b/app/code/Magento/TaxImportExport/Test/Unit/Controller/Adminhtml/Rate/ExportPostTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..744ad42c66d39d7358e7a28f2b98ec45fabadf11
--- /dev/null
+++ b/app/code/Magento/TaxImportExport/Test/Unit/Controller/Adminhtml/Rate/ExportPostTest.php
@@ -0,0 +1,103 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\TaxImportExport\Test\Unit\Controller\Adminhtml\Rate;
+
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+use Magento\Framework\App\Filesystem\DirectoryList;
+
+class ExportPostTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\TaxImportExport\Controller\Adminhtml\Rate\ExportPost
+     */
+    private $controller;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $fileFactoryMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $objectManagerMock;
+
+    /**
+     * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
+     */
+    private $objectManagerHelper;
+
+    protected function setUp()
+    {
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->fileFactoryMock = $this->getMock(
+            \Magento\Framework\App\Response\Http\FileFactory::class,
+            [],
+            [],
+            '',
+            false
+        );
+        $this->objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class);
+        $this->controller = $this->objectManagerHelper->getObject(
+            \Magento\TaxImportExport\Controller\Adminhtml\Rate\ExportPost::class,
+            [
+                'fileFactory' => $this->fileFactoryMock,
+                'objectManager' => $this->objectManagerMock
+            ]
+        );
+    }
+
+    public function testExecute()
+    {
+        $headers = new \Magento\Framework\DataObject(
+            [
+                'code' => __('Code'),
+                'country_name' => __('Country'),
+                'region_name' => __('State'),
+                'tax_postcode' => __('Zip/Post Code'),
+                'rate' => __('Rate'),
+                'zip_is_range' => __('Zip/Post is Range'),
+                'zip_from' => __('Range From'),
+                'zip_to' => __('Range To'),
+            ]
+        );
+        $template = '"{{code}}","{{country_name}}","{{region_name}}","{{tax_postcode}}","{{rate}}"' .
+            ',"{{zip_is_range}}","{{zip_from}}","{{zip_to}}"';
+        $content = $headers->toString($template);
+        $content .= "\n";
+        $storeMock = $this->getMock(\Magento\Store\Model\Store::class, [], [], '', false);
+        $storeCollectionMock = $this->objectManagerHelper->getCollectionMock(
+            \Magento\Store\Model\ResourceModel\Store\Collection::class,
+            []
+        );
+        $rateCollectionMock = $this->objectManagerHelper->getCollectionMock(
+            \Magento\Tax\Model\ResourceModel\Calculation\Rate\Collection::class,
+            []
+        );
+
+        $taxCollectionMock = $this->objectManagerHelper->getCollectionMock(
+            \Magento\Tax\Model\ResourceModel\Calculation\Rate\Title\Collection::class,
+            []
+        );
+        $storeCollectionMock->expects($this->once())->method('setLoadDefault')->willReturnSelf();
+        $rateTitleMock = $this->getMock(\Magento\Tax\Model\Calculation\Rate\Title::class, [], [], '', false);
+        $rateTitleMock->expects($this->once())->method('getCollection')->willReturn($taxCollectionMock);
+        $storeMock->expects($this->once())->method('getCollection')->willReturn($storeCollectionMock);
+        $this->objectManagerMock->expects($this->any())->method('create')->willReturnMap([
+            [\Magento\Store\Model\Store::class, [], $storeMock],
+            [\Magento\Tax\Model\Calculation\Rate\Title::class, [], $rateTitleMock],
+            [\Magento\Tax\Model\ResourceModel\Calculation\Rate\Collection::class, [], $rateCollectionMock]
+        ]);
+        $rateCollectionMock->expects($this->once())->method('joinCountryTable')->willReturnSelf();
+        $rateCollectionMock->expects($this->once())->method('joinRegionTable')->willReturnSelf();
+        $this->fileFactoryMock
+            ->expects($this->once())
+            ->method('create')
+            ->with('tax_rates.csv', $content, DirectoryList::VAR_DIR);
+        $this->controller->execute();
+    }
+}
diff --git a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js
index 449418f07c100c91e139231c704bb28fd8c9ae82..bfae1cf87030f45d8bbda74e8eb3d9f741f00201 100644
--- a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js
+++ b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js
@@ -538,7 +538,8 @@ define([
                         label: cell.config.label,
                         name: cell.name,
                         required: !!cell.config.validation,
-                        columnsHeaderClasses: cell.config.columnsHeaderClasses
+                        columnsHeaderClasses: cell.config.columnsHeaderClasses,
+                        sortOrder: cell.config.sortOrder
                     });
 
                     this.labels.push(data);
diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/date.js b/app/code/Magento/Ui/view/base/web/js/form/element/date.js
index 202cfe93069b02bad6ff888a51b9661a54109e54..eb8dfb4b4057e8c7d8cf274062788a5849114d09 100644
--- a/app/code/Magento/Ui/view/base/web/js/form/element/date.js
+++ b/app/code/Magento/Ui/view/base/web/js/form/element/date.js
@@ -53,13 +53,12 @@ define([
             pickerDefaultDateFormat: 'MM/dd/y', // ICU Date Format
             pickerDefaultTimeFormat: 'h:mm a', // ICU Time Format
 
+            elementTmpl: 'ui/form/element/date',
+
             /**
-             * Moment compatible format used for moment conversion
-             * of date from datePicker
+             * Format needed by moment timezone for conversion
              */
-            momentFormat: 'MM/DD/YYYY',
-
-            elementTmpl: 'ui/form/element/date',
+            timezoneFormat: 'YYYY-MM-DD HH:mm',
 
             listens: {
                 'value': 'onValueChange',
@@ -141,15 +140,17 @@ define([
          */
         onShiftedValueChange: function (shiftedValue) {
             var value,
-                formattedValue;
+                formattedValue,
+                momentValue;
 
             if (shiftedValue) {
+                momentValue = moment(shiftedValue, this.pickerDateTimeFormat);
+
                 if (this.options.showsTime) {
-                    formattedValue = moment(shiftedValue).format('YYYY-MM-DD HH:mm');
+                    formattedValue = moment(momentValue).format(this.timezoneFormat);
                     value = moment.tz(formattedValue, this.storeTimeZone).tz('UTC').toISOString();
                 } else {
-                    value = moment(shiftedValue, this.momentFormat);
-                    value = value.format(this.outputDateFormat);
+                    value = momentValue.format(this.outputDateFormat);
                 }
             } else {
                 value = '';
@@ -166,8 +167,6 @@ define([
          */
         prepareDateTimeFormats: function () {
             this.pickerDateTimeFormat = this.options.dateFormat;
-            this.momentFormat = this.options.dateFormat ?
-                    utils.convertToMomentFormat(this.options.dateFormat) : this.momentFormat;
 
             if (this.options.showsTime) {
                 this.pickerDateTimeFormat += ' ' + this.options.timeFormat;
diff --git a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/module/_toolbar.less b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/module/_toolbar.less
index 00b2c23450ff7881c5a9acca30df491b7001187c..782b78672f7aebd3d7038544dbb56884e680dd6d 100644
--- a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/module/_toolbar.less
+++ b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/module/_toolbar.less
@@ -81,9 +81,11 @@
         );
     }
 
-    .sorter.sort-desc {
-        &:before {
-            content: @icon-arrow-down;
+    .sorter {
+        .sort-desc {
+            &:before {
+                content: @icon-arrow-down;
+            }
         }
     }
 
diff --git a/app/design/frontend/Magento/luma/Magento_Customer/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Customer/web/css/source/_module.less
index 799094cf93d7cfa4ffcfb6b32a2767e93c882a06..3273df52b8d622146ab134184ec607503938e51a 100644
--- a/app/design/frontend/Magento/luma/Magento_Customer/web/css/source/_module.less
+++ b/app/design/frontend/Magento/luma/Magento_Customer/web/css/source/_module.less
@@ -319,6 +319,11 @@
 
     .order-products-toolbar {
         position: relative;
+
+        .toolbar-amount {
+            position: relative;
+            text-align: center;
+        }
     }
 }
 
diff --git a/app/design/frontend/Magento/luma/Magento_Review/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Review/web/css/source/_module.less
index 95ec8b694b1ca5a24dc9af66120acbc857294e5b..c8c885fafda19d5ca6592ff22f37ce0612f82694 100644
--- a/app/design/frontend/Magento/luma/Magento_Review/web/css/source/_module.less
+++ b/app/design/frontend/Magento/luma/Magento_Review/web/css/source/_module.less
@@ -40,6 +40,7 @@
 
     .review-control-vote {
         .lib-rating-vote();
+
         &:before {
             .lib-rating-icons-content(
                 @_icon-content: @icon-star-empty
@@ -47,6 +48,19 @@
         }
     }
 
+    //
+    //  Account Review list page
+    //  -----------------------------------------
+
+    .products-reviews-toolbar {
+        position: relative;
+
+        .toolbar-amount {
+            position: relative;
+            text-align: center;
+        }
+    }
+
     //
     //  Review product page
     //  -----------------------------------------
@@ -95,6 +109,7 @@
         .fieldset &-legend.legend {
             border-bottom: 0;
             line-height: 1.3;
+            margin-bottom: @indent__base;
             padding: 0;
 
             span {
@@ -105,8 +120,6 @@
                 display: block;
                 font-weight: 600;
             }
-
-            margin-bottom: @indent__base;
         }
 
         .fieldset &-field-ratings {
@@ -189,6 +202,7 @@
             margin-bottom: @indent__base;
         }
     }
+
     .page-main {
         .column {
             .review-add {
@@ -284,9 +298,6 @@
             a:not(:last-child) {
                 margin-right: 30px;
             }
-
-            .action.view span {
-            }
         }
     }
 
@@ -331,6 +342,7 @@
         .items {
             .item {
                 .lib-css(margin-bottom, @indent__base);
+
                 &:last-child {
                     margin-bottom: 0;
                 }
@@ -339,6 +351,7 @@
 
         .product-name {
             display: inline-block;
+
             &:not(:last-child) {
                 .lib-css(margin-bottom, @indent__xs);
             }
@@ -415,9 +428,6 @@
             width: 30%;
         }
 
-        .product-info {
-        }
-
         .review-details {
             margin: 0;
 
diff --git a/composer.json b/composer.json
index 7840f84720b6cac97073647c90c184315a80eb4b..11fe00b7ed45add98a8996bea8a480403d44a53c 100644
--- a/composer.json
+++ b/composer.json
@@ -151,7 +151,7 @@
         "magento/module-rss": "100.2.0-dev",
         "magento/module-rule": "100.2.0-dev",
         "magento/module-sales": "100.2.0-dev",
-        "magento/module-sales-inventory": "100.0.0-dev",
+        "magento/module-sales-inventory": "100.2.0-dev",
         "magento/module-sales-rule": "100.2.0-dev",
         "magento/module-sales-sequence": "100.2.0-dev",
         "magento/module-sample-data": "100.2.0-dev",
diff --git a/composer.lock b/composer.lock
index 7b3c6ccc9928df82fc72f6e397d1b98d3f2823d0..e69e12953fea2c150e1e063ddb9502148aad38ec 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,8 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "8c0f23eee8426e8aeba5a897f6f2ccbd",
-    "content-hash": "600aca1692cf3fe5c2ea1cbf66de09ab",
+    "hash": "01335ef9c76fd6d77bf6bd9236b84d03",
+    "content-hash": "07be52ec4880d0390acff2dd605a194d",
     "packages": [
         {
             "name": "braintree/braintree_php",
@@ -56,7 +56,7 @@
         },
         {
             "name": "colinmollenhour/cache-backend-file",
-            "version": "1.4.0",
+            "version": "1.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/colinmollenhour/Cm_Cache_Backend_File.git",
@@ -818,16 +818,16 @@
         },
         {
             "name": "paragonie/random_compat",
-            "version": "v2.0.3",
+            "version": "v2.0.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/paragonie/random_compat.git",
-                "reference": "c0125896dbb151380ab47e96c621741e79623beb"
+                "reference": "a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/paragonie/random_compat/zipball/c0125896dbb151380ab47e96c621741e79623beb",
-                "reference": "c0125896dbb151380ab47e96c621741e79623beb",
+                "url": "https://api.github.com/repos/paragonie/random_compat/zipball/a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e",
+                "reference": "a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e",
                 "shasum": ""
             },
             "require": {
@@ -862,7 +862,7 @@
                 "pseudorandom",
                 "random"
             ],
-            "time": "2016-10-17 15:23:22"
+            "time": "2016-11-07 23:38:38"
         },
         {
             "name": "pelago/emogrifier",
@@ -1189,16 +1189,16 @@
         },
         {
             "name": "seld/jsonlint",
-            "version": "1.4.1",
+            "version": "1.5.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/Seldaek/jsonlint.git",
-                "reference": "e827b5254d3e58c736ea2c5616710983d80b0b70"
+                "reference": "19495c181d6d53a0a13414154e52817e3b504189"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/e827b5254d3e58c736ea2c5616710983d80b0b70",
-                "reference": "e827b5254d3e58c736ea2c5616710983d80b0b70",
+                "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/19495c181d6d53a0a13414154e52817e3b504189",
+                "reference": "19495c181d6d53a0a13414154e52817e3b504189",
                 "shasum": ""
             },
             "require": {
@@ -1231,7 +1231,7 @@
                 "parser",
                 "validator"
             ],
-            "time": "2016-09-14 15:17:56"
+            "time": "2016-11-14 17:59:58"
         },
         {
             "name": "seld/phar-utils",
@@ -1390,16 +1390,16 @@
         },
         {
             "name": "symfony/event-dispatcher",
-            "version": "v2.8.12",
+            "version": "v2.8.15",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/event-dispatcher.git",
-                "reference": "889983a79a043dfda68f38c38b6dba092dd49cd8"
+                "reference": "25c576abd4e0f212e678fe8b2bd9a9a98c7ea934"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/889983a79a043dfda68f38c38b6dba092dd49cd8",
-                "reference": "889983a79a043dfda68f38c38b6dba092dd49cd8",
+                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/25c576abd4e0f212e678fe8b2bd9a9a98c7ea934",
+                "reference": "25c576abd4e0f212e678fe8b2bd9a9a98c7ea934",
                 "shasum": ""
             },
             "require": {
@@ -1446,20 +1446,20 @@
             ],
             "description": "Symfony EventDispatcher Component",
             "homepage": "https://symfony.com",
-            "time": "2016-07-28 16:56:28"
+            "time": "2016-10-13 01:43:15"
         },
         {
             "name": "symfony/filesystem",
-            "version": "v2.8.12",
+            "version": "v2.8.15",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/filesystem.git",
-                "reference": "44b499521defddf2eae17a18c811bbdae4f98bdf"
+                "reference": "a3784111af9f95f102b6411548376e1ae7c93898"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/filesystem/zipball/44b499521defddf2eae17a18c811bbdae4f98bdf",
-                "reference": "44b499521defddf2eae17a18c811bbdae4f98bdf",
+                "url": "https://api.github.com/repos/symfony/filesystem/zipball/a3784111af9f95f102b6411548376e1ae7c93898",
+                "reference": "a3784111af9f95f102b6411548376e1ae7c93898",
                 "shasum": ""
             },
             "require": {
@@ -1495,20 +1495,20 @@
             ],
             "description": "Symfony Filesystem Component",
             "homepage": "https://symfony.com",
-            "time": "2016-09-06 10:55:00"
+            "time": "2016-10-18 04:28:30"
         },
         {
             "name": "symfony/finder",
-            "version": "v3.1.5",
+            "version": "v3.2.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/finder.git",
-                "reference": "205b5ffbb518a98ba2ae60a52656c4a31ab00c6f"
+                "reference": "a69cb5d455b4885ca376dc5bb3e1155cc8c08c4b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/finder/zipball/205b5ffbb518a98ba2ae60a52656c4a31ab00c6f",
-                "reference": "205b5ffbb518a98ba2ae60a52656c4a31ab00c6f",
+                "url": "https://api.github.com/repos/symfony/finder/zipball/a69cb5d455b4885ca376dc5bb3e1155cc8c08c4b",
+                "reference": "a69cb5d455b4885ca376dc5bb3e1155cc8c08c4b",
                 "shasum": ""
             },
             "require": {
@@ -1517,7 +1517,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.1-dev"
+                    "dev-master": "3.2-dev"
                 }
             },
             "autoload": {
@@ -1544,20 +1544,20 @@
             ],
             "description": "Symfony Finder Component",
             "homepage": "https://symfony.com",
-            "time": "2016-09-28 00:11:12"
+            "time": "2016-12-13 09:39:43"
         },
         {
             "name": "symfony/process",
-            "version": "v2.8.12",
+            "version": "v2.8.15",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/process.git",
-                "reference": "024de37f8a6b9e5e8244d9eb3fcf3e467dd2a93f"
+                "reference": "1a1bd056395540d0bc549d39818316513565d278"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/process/zipball/024de37f8a6b9e5e8244d9eb3fcf3e467dd2a93f",
-                "reference": "024de37f8a6b9e5e8244d9eb3fcf3e467dd2a93f",
+                "url": "https://api.github.com/repos/symfony/process/zipball/1a1bd056395540d0bc549d39818316513565d278",
+                "reference": "1a1bd056395540d0bc549d39818316513565d278",
                 "shasum": ""
             },
             "require": {
@@ -1593,7 +1593,7 @@
             ],
             "description": "Symfony Process Component",
             "homepage": "https://symfony.com",
-            "time": "2016-09-29 14:03:54"
+            "time": "2016-11-24 00:43:03"
         },
         {
             "name": "tedivm/jshrink",
@@ -3242,16 +3242,16 @@
         },
         {
             "name": "friendsofphp/php-cs-fixer",
-            "version": "v1.12.2",
+            "version": "v1.13.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
-                "reference": "baa7112bef3b86c65fcfaae9a7a50436e3902b41"
+                "reference": "0ea4f7ed06ca55da1d8fc45da26ff87f261c4088"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/baa7112bef3b86c65fcfaae9a7a50436e3902b41",
-                "reference": "baa7112bef3b86c65fcfaae9a7a50436e3902b41",
+                "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/0ea4f7ed06ca55da1d8fc45da26ff87f261c4088",
+                "reference": "0ea4f7ed06ca55da1d8fc45da26ff87f261c4088",
                 "shasum": ""
             },
             "require": {
@@ -3296,7 +3296,7 @@
                 }
             ],
             "description": "A tool to automatically fix PHP code style",
-            "time": "2016-09-27 07:57:59"
+            "time": "2016-12-01 00:05:05"
         },
         {
             "name": "lusitanian/oauth",
@@ -3407,21 +3407,21 @@
         },
         {
             "name": "phpmd/phpmd",
-            "version": "2.4.3",
+            "version": "2.5.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpmd/phpmd.git",
-                "reference": "2b9c2417a18696dfb578b38c116cd0ddc19b256e"
+                "reference": "9298602a922cd8c46666df8d540a60bc5925ce55"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpmd/phpmd/zipball/2b9c2417a18696dfb578b38c116cd0ddc19b256e",
-                "reference": "2b9c2417a18696dfb578b38c116cd0ddc19b256e",
+                "url": "https://api.github.com/repos/phpmd/phpmd/zipball/9298602a922cd8c46666df8d540a60bc5925ce55",
+                "reference": "9298602a922cd8c46666df8d540a60bc5925ce55",
                 "shasum": ""
             },
             "require": {
                 "pdepend/pdepend": "^2.0.4",
-                "php": ">=5.3.0"
+                "php": ">=5.3.9"
             },
             "require-dev": {
                 "phpunit/phpunit": "^4.0",
@@ -3468,7 +3468,7 @@
                 "phpmd",
                 "pmd"
             ],
-            "time": "2016-04-04 11:52:04"
+            "time": "2016-11-23 20:33:32"
         },
         {
             "name": "phpunit/php-code-coverage",
@@ -3664,16 +3664,16 @@
         },
         {
             "name": "phpunit/php-token-stream",
-            "version": "1.4.8",
+            "version": "1.4.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-token-stream.git",
-                "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da"
+                "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
-                "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b",
+                "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b",
                 "shasum": ""
             },
             "require": {
@@ -3709,7 +3709,7 @@
             "keywords": [
                 "tokenizer"
             ],
-            "time": "2015-09-15 10:49:45"
+            "time": "2016-11-15 14:06:22"
         },
         {
             "name": "phpunit/phpunit",
@@ -3843,22 +3843,22 @@
         },
         {
             "name": "sebastian/comparator",
-            "version": "1.2.0",
+            "version": "1.2.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/comparator.git",
-                "reference": "937efb279bd37a375bcadf584dec0726f84dbf22"
+                "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22",
-                "reference": "937efb279bd37a375bcadf584dec0726f84dbf22",
+                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f",
+                "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f",
                 "shasum": ""
             },
             "require": {
                 "php": ">=5.3.3",
                 "sebastian/diff": "~1.2",
-                "sebastian/exporter": "~1.2"
+                "sebastian/exporter": "~1.2 || ~2.0"
             },
             "require-dev": {
                 "phpunit/phpunit": "~4.4"
@@ -3903,7 +3903,7 @@
                 "compare",
                 "equality"
             ],
-            "time": "2015-07-26 15:48:44"
+            "time": "2016-11-19 09:18:40"
         },
         {
             "name": "sebastian/diff",
@@ -4329,22 +4329,25 @@
         },
         {
             "name": "symfony/config",
-            "version": "v2.8.12",
+            "version": "v2.8.15",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/config.git",
-                "reference": "f8b1922bbda9d2ac86aecd649399040bce849fde"
+                "reference": "b522856007b258f46d5ee35d3b7b235c11e76e86"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/config/zipball/f8b1922bbda9d2ac86aecd649399040bce849fde",
-                "reference": "f8b1922bbda9d2ac86aecd649399040bce849fde",
+                "url": "https://api.github.com/repos/symfony/config/zipball/b522856007b258f46d5ee35d3b7b235c11e76e86",
+                "reference": "b522856007b258f46d5ee35d3b7b235c11e76e86",
                 "shasum": ""
             },
             "require": {
                 "php": ">=5.3.9",
                 "symfony/filesystem": "~2.3|~3.0.0"
             },
+            "require-dev": {
+                "symfony/yaml": "~2.7|~3.0.0"
+            },
             "suggest": {
                 "symfony/yaml": "To use the yaml reference dumper"
             },
@@ -4378,20 +4381,20 @@
             ],
             "description": "Symfony Config Component",
             "homepage": "https://symfony.com",
-            "time": "2016-09-14 20:31:12"
+            "time": "2016-12-10 08:21:45"
         },
         {
             "name": "symfony/dependency-injection",
-            "version": "v2.8.12",
+            "version": "v2.8.15",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/dependency-injection.git",
-                "reference": "ee9ec9ac2b046462d341e9de7c4346142d335e75"
+                "reference": "51a7b5385fb0f42e5edbdb2cfbad1a011ecdaee7"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/ee9ec9ac2b046462d341e9de7c4346142d335e75",
-                "reference": "ee9ec9ac2b046462d341e9de7c4346142d335e75",
+                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/51a7b5385fb0f42e5edbdb2cfbad1a011ecdaee7",
+                "reference": "51a7b5385fb0f42e5edbdb2cfbad1a011ecdaee7",
                 "shasum": ""
             },
             "require": {
@@ -4441,20 +4444,20 @@
             ],
             "description": "Symfony DependencyInjection Component",
             "homepage": "https://symfony.com",
-            "time": "2016-09-24 09:47:20"
+            "time": "2016-12-08 14:41:31"
         },
         {
             "name": "symfony/stopwatch",
-            "version": "v3.1.5",
+            "version": "v3.2.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/stopwatch.git",
-                "reference": "bb42806b12c5f89db4ebf64af6741afe6d8457e1"
+                "reference": "5b139e1c4290e6c7640ba80d9c9b5e49ef22b841"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/stopwatch/zipball/bb42806b12c5f89db4ebf64af6741afe6d8457e1",
-                "reference": "bb42806b12c5f89db4ebf64af6741afe6d8457e1",
+                "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5b139e1c4290e6c7640ba80d9c9b5e49ef22b841",
+                "reference": "5b139e1c4290e6c7640ba80d9c9b5e49ef22b841",
                 "shasum": ""
             },
             "require": {
@@ -4463,7 +4466,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.1-dev"
+                    "dev-master": "3.2-dev"
                 }
             },
             "autoload": {
@@ -4490,20 +4493,20 @@
             ],
             "description": "Symfony Stopwatch Component",
             "homepage": "https://symfony.com",
-            "time": "2016-06-29 05:41:56"
+            "time": "2016-06-29 05:43:10"
         },
         {
             "name": "symfony/yaml",
-            "version": "v2.8.12",
+            "version": "v2.8.15",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/yaml.git",
-                "reference": "e7540734bad981fe59f8ef14b6fc194ae9df8d9c"
+                "reference": "befb26a3713c97af90d25dd12e75621ef14d91ff"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/yaml/zipball/e7540734bad981fe59f8ef14b6fc194ae9df8d9c",
-                "reference": "e7540734bad981fe59f8ef14b6fc194ae9df8d9c",
+                "url": "https://api.github.com/repos/symfony/yaml/zipball/befb26a3713c97af90d25dd12e75621ef14d91ff",
+                "reference": "befb26a3713c97af90d25dd12e75621ef14d91ff",
                 "shasum": ""
             },
             "require": {
@@ -4539,7 +4542,7 @@
             ],
             "description": "Symfony Yaml Component",
             "homepage": "https://symfony.com",
-            "time": "2016-09-02 01:57:56"
+            "time": "2016-11-14 16:15:57"
         },
         {
             "name": "theseer/fdomdocument",
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/BasePriceStorageTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/BasePriceStorageTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..aad068ce6f0799feb342e93b3f94c6e6899c18c9
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/BasePriceStorageTest.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+
+/**
+ * BasePriceStorage test.
+ */
+class BasePriceStorageTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogBasePriceStorageV1';
+    const SERVICE_VERSION = 'V1';
+    const SIMPLE_PRODUCT_SKU = 'simple';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * Set up.
+     */
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * Test get method.
+     *
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testGet()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/base-prices-information',
+                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+        $response = $this->_webApiCall($serviceInfo, ['skus' => [self::SIMPLE_PRODUCT_SKU]]);
+        $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+        /** @var \Magento\Catalog\Api\Data\ProductInterface $product */
+        $product = $productRepository->get(self::SIMPLE_PRODUCT_SKU);
+
+        $this->assertNotEmpty($response);
+        $this->assertEquals($product->getPrice(), $response[0]['price']);
+        $this->assertEquals($product->getSku(), $response[0]['sku']);
+    }
+
+    /**
+     * Test update method.
+     *
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testUpdate()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/base-prices',
+                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Update',
+            ],
+        ];
+        $newPrice = 9999;
+        $storeId = 0;
+        $response = $this->_webApiCall(
+            $serviceInfo,
+            [
+                'prices' => [
+                    [
+                        'price' => $newPrice,
+                        'store_id' => $storeId,
+                        'sku' => self::SIMPLE_PRODUCT_SKU,
+                    ]
+                ]
+            ]
+        );
+        $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+        /** @var \Magento\Catalog\Api\Data\ProductInterface $product */
+        $product = $productRepository->get(self::SIMPLE_PRODUCT_SKU);
+
+        $this->assertNotEmpty($response);
+        $this->assertEquals($product->getPrice(), $newPrice);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CostStorageTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CostStorageTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6af9960a524dfe63910b51dbee08335af109d909
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CostStorageTest.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+
+/**
+ * CostStorage test.
+ */
+class CostStorageTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogCostStorageV1';
+    const SERVICE_VERSION = 'V1';
+    const SIMPLE_PRODUCT_SKU = 'simple';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * Set up.
+     */
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * Test get method.
+     *
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testGet()
+    {
+        $cost = 3057;
+        $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+        $productRepository->save($productRepository->get(self::SIMPLE_PRODUCT_SKU)->setData('cost', $cost));
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/cost-information',
+                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Delete',
+            ],
+        ];
+        $response = $this->_webApiCall($serviceInfo, ['skus' => [self::SIMPLE_PRODUCT_SKU]]);
+
+        /** @var \Magento\Catalog\Api\Data\ProductInterface $product */
+        $product = $productRepository->get(self::SIMPLE_PRODUCT_SKU);
+
+        $this->assertNotEmpty($response);
+        $this->assertEquals($product->getCost(), $cost);
+    }
+
+    /**
+     * Test update method.
+     *
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testUpdate()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/cost',
+                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Update',
+            ],
+        ];
+        $storeId = 0;
+        $newCost = 31337;
+        $response = $this->_webApiCall(
+            $serviceInfo,
+            [
+                'prices' => [
+                    [
+                        'cost' => $newCost,
+                        'store_id' => $storeId,
+                        'sku' => self::SIMPLE_PRODUCT_SKU,
+                    ]
+                ]
+            ]
+        );
+        $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+        /** @var \Magento\Catalog\Api\Data\ProductInterface $product */
+        $product = $productRepository->get(self::SIMPLE_PRODUCT_SKU);
+        $this->assertNotEmpty($response);
+        $this->assertEquals($product->getCost(), $newCost);
+    }
+
+    /**
+     * Test delete method.
+     *
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testDelete()
+    {
+        $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+        $productRepository->save($productRepository->get(self::SIMPLE_PRODUCT_SKU)->setData('cost', 777));
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/cost-delete',
+                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Delete',
+            ],
+        ];
+        $response = $this->_webApiCall($serviceInfo, ['skus' => [self::SIMPLE_PRODUCT_SKU]]);
+        $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+        /** @var \Magento\Catalog\Api\Data\ProductInterface $product */
+        $product = $productRepository->get(self::SIMPLE_PRODUCT_SKU);
+        $this->assertTrue($response);
+        $this->assertNull($product->getCost());
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductCustomOptionRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductCustomOptionRepositoryTest.php
index 0b761d8c191ab621bf75792a06e5e7e6ca98c1e1..6a09bea591cb8dca4eca1542f79971cbb92c7017 100644
--- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductCustomOptionRepositoryTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductCustomOptionRepositoryTest.php
@@ -391,6 +391,7 @@ class ProductCustomOptionRepositoryTest extends WebapiAbstract
      */
     public function testUpdateNegative($optionData, $message)
     {
+        $this->_markTestAsRestOnly();
         $productSku = 'simple';
         /** @var ProductRepository $productRepository */
         $productRepository = $this->objectManager->create(ProductRepository::class);
@@ -403,18 +404,9 @@ class ProductCustomOptionRepositoryTest extends WebapiAbstract
                 'resourcePath' => '/V1/products/options/' . $optionId,
                 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
             ],
-            'soap' => [
-                'service' => self::SERVICE_NAME,
-                'serviceVersion' => 'V1',
-                'operation' => self::SERVICE_NAME . 'Save',
-            ],
         ];
 
-        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
-            $this->setExpectedException('SoapFault');
-        } else {
-            $this->setExpectedException('Exception', $message, 400);
-        }
+        $this->setExpectedException('Exception', $message, 400);
         $this->_webApiCall($serviceInfo, ['option' => $optionData]);
     }
 
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php
index cd02c6d4d7500ef9adf7d17ac9f866bfc8ef0711..ed641ac0f85b872717b52fbadc46a4d12b7d218e 100644
--- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php
@@ -134,15 +134,6 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract
         ];
     }
 
-    private function markAreaAsSecure()
-    {
-        /** @var \Magento\Framework\Registry $registry */
-        $registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
-            ->get(\Magento\Framework\Registry::class);
-        $registry->unregister("isSecureArea");
-        $registry->register("isSecureArea", true);
-    }
-
     /**
      * Test removing association between product and website 1
      * @magentoApiDataFixture Magento/Catalog/_files/product_with_two_websites.php
@@ -169,9 +160,6 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract
             $response[ProductInterface::EXTENSION_ATTRIBUTES_KEY]["website_ids"],
             $websitesData["website_ids"]
         );
-        $this->deleteProduct($productBuilder[ProductInterface::SKU]);
-        $this->markAreaAsSecure();
-        $website->delete();
     }
 
     /**
@@ -198,9 +186,6 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract
             $response[ProductInterface::EXTENSION_ATTRIBUTES_KEY]["website_ids"],
             $websitesData["website_ids"]
         );
-        $this->deleteProduct($productBuilder[ProductInterface::SKU]);
-        $this->markAreaAsSecure();
-        $website->delete();
     }
 
     /**
@@ -222,7 +207,7 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract
         $websitesData = [
             'website_ids' => [
                 1,
-                $website->getId(),
+                (int) $website->getId(),
             ]
         ];
         $productBuilder[ProductInterface::EXTENSION_ATTRIBUTES_KEY] = $websitesData;
@@ -231,9 +216,6 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract
             $response[ProductInterface::EXTENSION_ATTRIBUTES_KEY]["website_ids"],
             $websitesData["website_ids"]
         );
-        $this->deleteProduct($productBuilder[ProductInterface::SKU]);
-        $this->markAreaAsSecure();
-        $website->delete();
     }
 
     /**
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/TierPriceStorageTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/TierPriceStorageTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..232c63257215036e414236fba818ff876da97c18
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/TierPriceStorageTest.php
@@ -0,0 +1,231 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+
+/**
+ * TierPriceStorage test.
+ */
+class TierPriceStorageTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogTierPriceStorageV1';
+    const SERVICE_VERSION = 'V1';
+    const SIMPLE_PRODUCT_SKU = 'simple';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * Set up.
+     */
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * Test get method.
+     *
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testGet()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/tier-prices-information',
+                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+        $response = $this->_webApiCall($serviceInfo, ['skus' => [self::SIMPLE_PRODUCT_SKU]]);
+        $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+        /** @var \Magento\Catalog\Api\Data\ProductInterface $product */
+        $tierPrices = $productRepository->get(self::SIMPLE_PRODUCT_SKU)->getTierPrices();
+        $this->assertNotEmpty($response);
+        $this->assertEquals(count($response), count($tierPrices));
+
+        foreach ($response as $item) {
+            $this->assertTrue($this->isPriceCorrect($item, $tierPrices));
+        }
+    }
+
+    /**
+     * Test update method.
+     *
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testUpdate()
+    {
+        $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+        $prices = $productRepository->get(self::SIMPLE_PRODUCT_SKU)->getTierPrices();
+        $tierPrice = array_shift($prices);
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/tier-prices',
+                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Update',
+            ],
+        ];
+        $newPrice = [
+            'price' => 40,
+            'price_type' => \Magento\Catalog\Api\Data\TierPriceInterface::PRICE_TYPE_DISCOUNT,
+            'website_id' => 0,
+            'sku' => self::SIMPLE_PRODUCT_SKU,
+            'customer_group' => 'ALL GROUPS',
+            'quantity' => 7778
+        ];
+        $updatedPrice = [
+            'price' => 778,
+            'price_type' => \Magento\Catalog\Api\Data\TierPriceInterface::PRICE_TYPE_FIXED,
+            'website_id' => 0,
+            'sku' => self::SIMPLE_PRODUCT_SKU,
+            'customer_group' => 'ALL GROUPS',
+            'quantity' => $tierPrice->getQty()
+        ];
+        $response = $this->_webApiCall($serviceInfo, ['prices' => [$updatedPrice, $newPrice]]);
+        $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+        $tierPrices = $productRepository->get(self::SIMPLE_PRODUCT_SKU)->getTierPrices();
+        $this->assertTrue($response);
+        $this->assertTrue($this->isPriceCorrect($newPrice, $tierPrices));
+        $this->assertTrue($this->isPriceCorrect($updatedPrice, $tierPrices));
+    }
+
+    /**
+     * Test replace method.
+     *
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testReplace()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/tier-prices',
+                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Replace',
+            ],
+        ];
+        $newPrices = [
+            [
+                'price' => 50,
+                'price_type' => \Magento\Catalog\Api\Data\TierPriceInterface::PRICE_TYPE_DISCOUNT,
+                'website_id' => 0,
+                'sku' => self::SIMPLE_PRODUCT_SKU,
+                'customer_group' => 'general',
+                'quantity' => 7778
+            ],
+            [
+                'price' => 70,
+                'price_type' => \Magento\Catalog\Api\Data\TierPriceInterface::PRICE_TYPE_FIXED,
+                'website_id' => 0,
+                'sku' => self::SIMPLE_PRODUCT_SKU,
+                'customer_group' => 'general',
+                'quantity' => 33
+            ]
+        ];
+        $response = $this->_webApiCall($serviceInfo, ['prices' => $newPrices]);
+        $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+        /** @var \Magento\Catalog\Api\Data\ProductInterface $product */
+        $tierPrices = $productRepository->get(self::SIMPLE_PRODUCT_SKU)->getTierPrices();
+        $this->assertTrue($response);
+        $this->assertEquals(count($newPrices), count($tierPrices));
+
+        foreach ($newPrices as $newPrice) {
+            $this->assertTrue($this->isPriceCorrect($newPrice, $tierPrices));
+        }
+    }
+
+    /**
+     * Test delete method.
+     *
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testDelete()
+    {
+        $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+        $tierPrices = $productRepository->get(self::SIMPLE_PRODUCT_SKU)->getTierPrices();
+        $pricesToStore = array_pop($tierPrices);
+        $pricesToDelete = [];
+        foreach ($tierPrices as $tierPrice) {
+            $tierPriceValue = $tierPrice->getExtensionAttributes()->getPercentageValue()
+                ?: $tierPrice->getValue();
+            $priceType = $tierPrice->getExtensionAttributes()->getPercentageValue()
+                ? \Magento\Catalog\Api\Data\TierPriceInterface::PRICE_TYPE_DISCOUNT
+                : \Magento\Catalog\Api\Data\TierPriceInterface::PRICE_TYPE_FIXED;
+            $customerGroup = $tierPrice->getCustomerGroupId() == \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID
+                ? 'NOT LOGGED IN'
+                : 'ALL GROUPS';
+            $pricesToDelete[] = [
+                'price' => $tierPriceValue,
+                'price_type' => $priceType,
+                'website_id' => 0,
+                'customer_group' => $customerGroup,
+                'sku' => self::SIMPLE_PRODUCT_SKU,
+                'quantity' => $tierPrice->getQty()
+
+            ];
+        }
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/tier-prices-delete',
+                'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Delete',
+            ],
+        ];
+        $response = $this->_webApiCall($serviceInfo, ['prices' => $pricesToDelete]);
+        $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+        $tierPrices = $productRepository->get(self::SIMPLE_PRODUCT_SKU)->getTierPrices();
+        $tierPrice = $tierPrices[0];
+        $this->assertTrue($response);
+        $this->assertEquals(1, count($tierPrices));
+        $this->assertEquals($pricesToStore, $tierPrice);
+    }
+
+    /**
+     * Check prise exists and is correct.
+     *
+     * @param array $price
+     * @param array $tierPrices
+     * @return bool
+     */
+    private function isPriceCorrect(array $price, array $tierPrices)
+    {
+        $isCorrect = false;
+
+        foreach ($tierPrices as $tierPrice) {
+            $priceIsCorrect = $price['price_type'] === \Magento\Catalog\Api\Data\TierPriceInterface::PRICE_TYPE_DISCOUNT
+                ? (float)$tierPrice->getExtensionAttributes()->getPercentageValue() === (float)$price['price']
+                : (float)$tierPrice->getValue() === (float)$price['price'];
+            if (
+                $priceIsCorrect
+                && (int)$tierPrice->getQty() === (int)$price['quantity']
+                && $tierPrice->getExtensionAttributes()->getWebsiteId() == $price['website_id']
+            ) {
+                $isCorrect = true;
+            }
+        }
+
+        return $isCorrect;
+    }
+}
diff --git a/dev/tests/functional/.htaccess.sample b/dev/tests/functional/.htaccess.sample
index f5c3be7db01e97c551085e09a493fceb11e2ad1f..f1e60cf9b67e91779153e4c9d9f780c8f7bc9438 100644
--- a/dev/tests/functional/.htaccess.sample
+++ b/dev/tests/functional/.htaccess.sample
@@ -1,6 +1,6 @@
 ##############################################
 ## Allow access to command.php and website.php
-    <FilesMatch "command.php|website.php">
+    <FilesMatch "command.php|website.php|export.php">
          order allow,deny
          allow from all
     </FilesMatch>
diff --git a/dev/tests/functional/composer.json b/dev/tests/functional/composer.json
index f170114a4ea8348714531af55ca805bb5e3442fe..3567ec530f437996c0ed28d792ebd929d2188e0c 100644
--- a/dev/tests/functional/composer.json
+++ b/dev/tests/functional/composer.json
@@ -1,6 +1,6 @@
 {
     "require": {
-        "magento/mtf": "1.0.0-rc50",
+        "magento/mtf": "1.0.0-rc51",
         "php": "~5.6.5|7.0.2|~7.0.6",
         "phpunit/phpunit": "~4.8.0|~5.5.0",
         "phpunit/phpunit-selenium": ">=1.2"
diff --git a/dev/tests/functional/etc/di.xml b/dev/tests/functional/etc/di.xml
index 69951a2cc1b86248040074c45ee967c93dc0bb82..b21e507a5af023b18326d2c1cf5bc038a5abdb3a 100644
--- a/dev/tests/functional/etc/di.xml
+++ b/dev/tests/functional/etc/di.xml
@@ -6,6 +6,11 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
+    <preference for="Magento\Mtf\Util\Command\File\ExportInterface" type="\Magento\Mtf\Util\Command\File\Export" />
+    <preference for="Magento\Mtf\Util\Command\File\Export\ReaderInterface" type="\Magento\Mtf\Util\Command\File\Export\Reader" />
+
+    <type name="\Magento\Mtf\Util\Command\File\Export" shared="false" />
+
     <virtualType name="Magento\Mtf\Config\SchemaLocator\Config" type="Magento\Mtf\Config\SchemaLocator">
         <arguments>
             <argument name="schemaPath" xsi:type="string">etc/config.xsd</argument>
@@ -13,4 +18,22 @@
     </virtualType>
 
     <type name="Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator" shared="true" />
+
+    <type name="Magento\Mtf\Util\Command\File\Export\Reader">
+        <arguments>
+            <argument name="template" xsi:type="string">\w*?\.csv</argument>
+        </arguments>
+    </type>
+
+    <virtualType name="Magento\Mtf\Util\Command\File\Export\ProductReader" type="Magento\Mtf\Util\Command\File\Export\Reader">
+        <arguments>
+            <argument name="template" xsi:type="string">catalog_product.*?\.csv</argument>
+        </arguments>
+    </virtualType>
+
+    <virtualType name="Magento\Mtf\Util\Command\File\Export\CustomerReader" type="Magento\Mtf\Util\Command\File\Export\Reader">
+        <arguments>
+            <argument name="template" xsi:type="string">customer.*?\.csv</argument>
+        </arguments>
+    </virtualType>
 </config>
diff --git a/dev/tests/functional/lib/Magento/Mtf/Client/Element/SuggestElement.php b/dev/tests/functional/lib/Magento/Mtf/Client/Element/SuggestElement.php
index 71d4a84b1161292b668899513878d6589e64d9e9..6eebcbc3529c1e191de837c3b03229828fe1b7d4 100644
--- a/dev/tests/functional/lib/Magento/Mtf/Client/Element/SuggestElement.php
+++ b/dev/tests/functional/lib/Magento/Mtf/Client/Element/SuggestElement.php
@@ -60,6 +60,13 @@ class SuggestElement extends SimpleElement
      */
     protected $closeButton = '[data-action="close-advanced-select"]';
 
+    /**
+     * Searched count.
+     *
+     * @var string
+     */
+    protected $searchedCount = '[class*=search-count]';
+
     /**
      * Set value.
      *
@@ -77,6 +84,12 @@ class SuggestElement extends SimpleElement
         }
         $this->keys([$value]);
         $searchedItem = $this->find(sprintf($this->resultItem, $value), Locator::SELECTOR_XPATH);
+        $searchedCountElements = $this->find($this->searchedCount);
+        $this->waitUntil(
+            function () use ($searchedCountElements) {
+                return $searchedCountElements->isVisible() ? true : null;
+            }
+        );
         $searchedItem->click();
         $closeButton = $this->find($this->closeButton);
         if ($closeButton->isVisible()) {
diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php
index 96be468a6eb377f619339c02a2be00835f8425eb..db39bdcb5b7a5e1e323ee434b2e8b1d744b0570a 100644
--- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php
+++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php
@@ -7,7 +7,6 @@
 namespace Magento\Mtf\Util\Command;
 
 use Magento\Mtf\Util\Protocol\CurlInterface;
-use Magento\Mtf\ObjectManager;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 
 /**
@@ -28,7 +27,6 @@ class Cli
     private $transport;
 
     /**
-     * @constructor
      * @param CurlTransport $transport
      */
     public function __construct(CurlTransport $transport)
@@ -61,6 +59,6 @@ class Cli
     private function prepareUrl($command, array $options)
     {
         $command .= ' ' . implode(' ', $options);
-        return $_ENV['app_frontend_url'] . Cli::URL . '?command=' . urlencode($command);
+        return $_ENV['app_frontend_url'] . self::URL . '?command=' . urlencode($command);
     }
 }
diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli/Indexer.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli/Indexer.php
new file mode 100644
index 0000000000000000000000000000000000000000..1e066440c7c3d98da1803c7f5b8d793116be66d9
--- /dev/null
+++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli/Indexer.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Mtf\Util\Command\Cli;
+
+use Magento\Mtf\Util\Command\Cli;
+
+/**
+ * Handle reindexing for tests executions.
+ */
+class Indexer extends Cli
+{
+    /**
+     * Parameter for reindex command.
+     */
+    const PARAM_INDEXER_REINDEX = 'indexer:reindex';
+
+    /**
+     * Run reindex.
+     *
+     * @param array $indexes [optional]
+     * @return void
+     */
+    public function reindex(array $indexes = [])
+    {
+        $params = '';
+        if (!empty($indexes)) {
+            $params = implode(' ', $indexes);
+        }
+        parent::execute(Indexer::PARAM_INDEXER_REINDEX . ' ' . $params);
+    }
+}
diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export.php
new file mode 100644
index 0000000000000000000000000000000000000000..6d5defadbc44a5d30e69423cafe96653450f51bf
--- /dev/null
+++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export.php
@@ -0,0 +1,131 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Mtf\Util\Command\File;
+
+use Magento\Mtf\ObjectManagerInterface;
+use Magento\Mtf\Util\Command\File\Export\Data;
+use Magento\Mtf\Util\Command\File\Export\ReaderInterface;
+
+/**
+ * Get Exporting file from the Magento.
+ */
+class Export implements ExportInterface
+{
+    /**
+     * Path to the Reader.
+     *
+     * @var string
+     */
+    private $readerPath = 'Magento\Mtf\Util\Command\File\Export\%sReader';
+
+    /**
+     * Object manager instance.
+     *
+     * @var ObjectManagerInterface
+     */
+    private $objectManager;
+
+    /**
+     * File reader for Magento export files.
+     *
+     * @var ReaderInterface
+     */
+    private $reader;
+
+    /**
+     * @param ObjectManagerInterface $objectManager
+     * @param string $type [optional]
+     */
+    public function __construct(ObjectManagerInterface $objectManager, $type = 'product')
+    {
+        $this->objectManager = $objectManager;
+        $this->reader = $this->getReader($type);
+    }
+
+    /**
+     * Get reader for export files.
+     *
+     * @param string $type
+     * @return ReaderInterface
+     * @throws \ReflectionException
+     */
+    private function getReader($type)
+    {
+        $readerPath = sprintf($this->readerPath, ucfirst($type));
+        try {
+            return $this->objectManager->create($readerPath);
+        } catch (\ReflectionException $e) {
+            throw new \ReflectionException("Virtual type '$readerPath' does not exist. Please, check it in di.xml.");
+        }
+    }
+
+    /**
+     * Get the export file by name.
+     *
+     * @param string $name
+     * @return Data|null
+     */
+    public function getByName($name)
+    {
+        $this->reader->getData();
+        foreach ($this->reader->getData() as $file) {
+            if ($file->getName() === $name) {
+                return $file;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Get latest created the export file.
+     *
+     * @return Data|null
+     */
+    public function getLatest()
+    {
+        $max = 0;
+        $latest = null;
+        foreach ($this->reader->getData() as $file) {
+            if ($file->getDate() > $max) {
+                $max = $file->getDate();
+                $latest = $file;
+            }
+        }
+
+        return $latest;
+    }
+
+    /**
+     * Get all export files by date range using unix time stamp.
+     *
+     * @param string $start
+     * @param string $end
+     * @return Data[]
+     */
+    public function getByDateRange($start, $end)
+    {
+        $files = [];
+        foreach ($this->reader->getData() as $file) {
+            if ($file->getDate() > $start && $file->getDate() < $end) {
+                $files[] = $file;
+            }
+        }
+
+        return $files;
+    }
+
+    /**
+     * Get all export files.
+     *
+     * @return Data[]
+     */
+    public function getAll()
+    {
+        return $this->reader->getData();
+    }
+}
diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Data.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Data.php
new file mode 100644
index 0000000000000000000000000000000000000000..a6756aac0052a28bc04cc7c7d420c4ace8d5c472
--- /dev/null
+++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Data.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Mtf\Util\Command\File\Export;
+
+/**
+ * Data mapping for Export file.
+ */
+class Data
+{
+    /**
+     * File data.
+     *
+     * @var array
+     */
+    private $data;
+
+    /**
+     * @param array $data
+     */
+    public function __construct(array $data)
+    {
+        $this->data = $data;
+    }
+
+    /**
+     * Get file name.
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->data['name'];
+    }
+
+    /**
+     * Get file content.
+     *
+     * @return string
+     */
+    public function getContent()
+    {
+        return $this->data['content'];
+    }
+
+    /**
+     * Get file creation date.
+     *
+     * @return string
+     */
+    public function getDate()
+    {
+        return $this->data['date'];
+    }
+}
diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php
new file mode 100644
index 0000000000000000000000000000000000000000..3a8287daae2ab54cc8adbd8fff2249864cbed9a5
--- /dev/null
+++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Mtf\Util\Command\File\Export;
+
+use Magento\Mtf\ObjectManagerInterface;
+use Magento\Mtf\Util\Protocol\CurlTransport;
+use Magento\Mtf\Util\Protocol\CurlInterface;
+
+/**
+ * File reader for Magento export files.
+ */
+class Reader implements ReaderInterface
+{
+    /**
+     * Pattern for file name in Magento.
+     *
+     * @var string
+     */
+    private $template;
+
+    /**
+     * Object manager instance.
+     *
+     * @var ObjectManagerInterface
+     */
+    private $objectManager;
+
+    /**
+     * Curl transport protocol.
+     *
+     * @var CurlTransport
+     */
+    private $transport;
+
+    /**
+     * @param ObjectManagerInterface $objectManager
+     * @param CurlTransport $transport
+     * @param string $template
+     */
+    public function __construct(ObjectManagerInterface $objectManager, CurlTransport $transport, $template)
+    {
+        $this->objectManager = $objectManager;
+        $this->template = $template;
+        $this->transport = $transport;
+    }
+
+    /**
+     * Exporting files as Data object from Magento.
+     *
+     * @return Data[]
+     */
+    public function getData()
+    {
+        $data = [];
+        foreach ($this->getFiles() as $file) {
+            $data[] = $this->objectManager->create(Data::class, ['data' => $file]);
+        }
+
+        return $data;
+    }
+
+    /**
+     * Get files by template from the Magento.
+     *
+     * @return array
+     */
+    private function getFiles()
+    {
+        $this->transport->write($this->prepareUrl(), [], CurlInterface::GET);
+        $serializedFiles = $this->transport->read();
+        $this->transport->close();
+
+        return unserialize($serializedFiles);
+    }
+
+    /**
+     * Prepare url.
+     *
+     * @return string
+     */
+    private function prepareUrl()
+    {
+        return $_ENV['app_frontend_url'] . self::URL . '?template=' . urlencode($this->template);
+    }
+}
diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..5d305513ec68080ec4e7ec6bad8e776f8653bf15
--- /dev/null
+++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Mtf\Util\Command\File\Export;
+
+/**
+ * File reader interface for Magento export files.
+ */
+interface ReaderInterface
+{
+    /**
+     * Url to export.php.
+     */
+    const URL = 'dev/tests/functional/utils/export.php';
+
+    /**
+     * Exporting files as Data object from Magento.
+     *
+     * @return Data[]
+     */
+    public function getData();
+}
diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/ExportInterface.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/ExportInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..0bc4f9e59a2433b1078805e8431f9f45d8d34e20
--- /dev/null
+++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/ExportInterface.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Mtf\Util\Command\File;
+
+use Magento\Mtf\Util\Command\File\Export\Data;
+
+/**
+ * Interface for getting Exporting file from the Magento.
+ */
+interface ExportInterface
+{
+    /**
+     * Get the export file by name.
+     *
+     * @param string $name
+     * @return Data|null
+     */
+    public function getByName($name);
+
+    /**
+     * Get latest created the export file.
+     *
+     * @return Data|null
+     */
+    public function getLatest();
+
+    /**
+     * Get all export files by date range using unix time stamp.
+     *
+     * @param string $start
+     * @param string $end
+     * @return Data[]
+     */
+    public function getByDateRange($start, $end);
+
+    /**
+     * Get all export files.
+     *
+     * @return Data[]
+     */
+    public function getAll();
+}
diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php
index 611f46894c8bca850d10a519fe7a2850f31b5533..d0c4be34888d2ae863173fbbedc203c08d95fb90 100644
--- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php
+++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php
@@ -58,6 +58,6 @@ class Website
      */
     private function prepareUrl($websiteCode)
     {
-        return $_ENV['app_frontend_url'] . Website::URL . '?website_code=' . urlencode($websiteCode);
+        return $_ENV['app_frontend_url'] . self::URL . '?website_code=' . urlencode($websiteCode);
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Menu.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Menu.php
index 9a06c2c3c8e313d8e3585c4b03706d781b09eae4..2faac2a19d09c8b35134f1cb46865da111676d81 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Menu.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Menu.php
@@ -100,4 +100,31 @@ class Menu extends Block
         $this->_rootElement->find($subMenuItem, Locator::SELECTOR_XPATH)->click();
         $this->waitForElementNotVisible($subMenuSelector, Locator::SELECTOR_XPATH);
     }
+
+    /**
+     * Check if menu item is visible.
+     *
+     * @param string $menuItem
+     * @return bool
+     */
+    public function isMenuItemVisible($menuItem)
+    {
+        $menuChain = array_map('trim', explode('>', $menuItem));
+        $mainMenu = $menuChain[0];
+        $subMenu = isset($menuChain[1]) ? $menuChain[1] : null;
+
+        $mainMenuElement = $this->_rootElement->find(sprintf($this->mainMenu, $mainMenu), Locator::SELECTOR_XPATH);
+        if (!$mainMenuElement->isVisible()) {
+            return false;
+        }
+        if ($subMenu === null) {
+            return true;
+        }
+        $mainMenuElement->click();
+
+        $subMenuSelector = sprintf($this->subMenu, $mainMenu);
+        $this->waitForElementVisible($subMenuSelector, Locator::SELECTOR_XPATH);
+        $subMenuItem = $subMenuSelector . sprintf($this->subMenuItem, $subMenu);
+        return $this->_rootElement->find($subMenuItem, Locator::SELECTOR_XPATH)->isVisible();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Messages.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Messages.php
index 9c8b0beee9162c276f20ad81c15b51a6b4ea523b..4ac95b73d7f67bd1f5bcc75c8f7d58e3c4bc3fb2 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Messages.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Messages.php
@@ -6,28 +6,13 @@
 
 namespace Magento\Backend\Test\Block;
 
-use Magento\Mtf\Block\Block;
 use Magento\Mtf\Client\Locator;
 
 /**
- * Global messages block.
+ * Backend Messages block.
  */
-class Messages extends Block
+class Messages extends \Magento\Ui\Test\Block\Messages
 {
-    /**
-     * Success message selector.
-     *
-     * @var string
-     */
-    protected $successMessage = '[data-ui-id$=message-success]';
-
-    /**
-     * Last success message selector.
-     *
-     * @var string
-     */
-    protected $lastSuccessMessage = '[data-ui-id$=message-success]:last-child';
-
     /**
      * Message link.
      *
@@ -35,97 +20,6 @@ class Messages extends Block
      */
     protected $messageLink = "//a[contains(.,'%s')]";
 
-    /**
-     * Error message selector.
-     *
-     * @var string
-     */
-    protected $errorMessage = '[data-ui-id$=message-error]';
-
-    /**
-     * Notice message selector.
-     *
-     * @var string
-     */
-    protected $noticeMessage = '[data-ui-id$=message-notice]';
-
-    /**
-     * Warning message selector.
-     *
-     * @var string
-     */
-    protected $warningMessage = '[data-ui-id$=message-warning]';
-
-    /**
-     * Wait for success message.
-     *
-     * @return bool
-     */
-    public function waitSuccessMessage()
-    {
-        return $this->waitForElementVisible($this->successMessage, Locator::SELECTOR_CSS);
-    }
-
-    /**
-     * Get all success messages which are present on the page.
-     *
-     * @return array
-     */
-    public function getSuccessMessages()
-    {
-        $this->waitForElementVisible($this->successMessage);
-        $elements = $this->_rootElement->getElements($this->successMessage);
-
-        $messages = [];
-        foreach ($elements as $element) {
-            $messages[] = $element->getText();
-        }
-
-        return $messages;
-    }
-
-    /**
-     * Get last success message which is present on the page.
-     *
-     * @return string
-     */
-    public function getSuccessMessage()
-    {
-        $this->waitForElementVisible($this->successMessage);
-
-        return $this->_rootElement->find($this->lastSuccessMessage)->getText();
-    }
-
-    /**
-     * Wait for element is visible in the page.
-     *
-     * @param string $selector
-     * @param string $strategy
-     * @return bool|null
-     */
-    public function waitForElementVisible($selector, $strategy = Locator::SELECTOR_CSS)
-    {
-        $browser = $this->browser;
-        return $browser->waitUntil(
-            function () use ($browser, $selector, $strategy) {
-                $message = $browser->find($selector, $strategy);
-                return $message->isVisible() ? true : null;
-            }
-        );
-    }
-
-    /**
-     * Get all error message which is present on the page.
-     *
-     * @return string
-     */
-    public function getErrorMessage()
-    {
-        return $this->_rootElement
-            ->find($this->errorMessage, Locator::SELECTOR_CSS)
-            ->getText();
-    }
-
     /**
      * Click on link in the message which is present on the page.
      *
@@ -175,26 +69,4 @@ class Messages extends Block
     {
         return $this->waitForElementVisible($this->noticeMessage, Locator::SELECTOR_CSS);
     }
-
-    /**
-     * Get notice message which is present on the page.
-     *
-     * @return string
-     */
-    public function getNoticeMessage()
-    {
-        $this->waitForElementVisible($this->noticeMessage);
-        return $this->_rootElement->find($this->noticeMessage)->getText();
-    }
-
-    /**
-     * Get warning message which is present on the page.
-     *
-     * @return string
-     */
-    public function getWarningMessage()
-    {
-        $this->waitForElementVisible($this->warningMessage);
-        return $this->_rootElement->find($this->warningMessage)->getText();
-    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertMenuItemNotVisible.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertMenuItemNotVisible.php
new file mode 100644
index 0000000000000000000000000000000000000000..181e88d1a98f43003ccb3b9a56793b02c19b4973
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertMenuItemNotVisible.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Backend\Test\Constraint;
+
+use Magento\Backend\Test\Page\Adminhtml\Dashboard;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert menu item availability.
+ */
+class AssertMenuItemNotVisible extends AbstractConstraint
+{
+    /**
+     * Assert that menu item is not visible in dashboard menu.
+     *
+     * @param Dashboard $dashboard
+     * @param string $menuItem
+     * @return void
+     */
+    public function processAssert(Dashboard $dashboard, $menuItem)
+    {
+        $dashboard->open();
+
+        \PHPUnit_Framework_Assert::assertFalse(
+            $dashboard->getMenuBlock()->isMenuItemVisible($menuItem),
+            'Menu item ' . $menuItem . '  is supposed to be not visible.'
+        );
+    }
+
+    /**
+     * Returns a string representation of successful assertion.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Menu item is not visible in dashboard menu.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/Dashboard.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/Dashboard.xml
index db800f2c9ea9e89be3218932ec959a3b03339b50..5f5c6036ddcd4eadd0148d09ff2cd6e9b114f925 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/Dashboard.xml
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/Dashboard.xml
@@ -7,6 +7,7 @@
  -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/pages.xsd">
     <page name="Dashboard" area="Adminhtml" mca="admin/dashboard" module="Magento_Backend">
+        <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator="#messages" strategy="css selector" />
         <block name="adminPanelHeader" class="Magento\Backend\Test\Block\Page\Header" locator=".page-header" strategy="css selector" />
         <block name="titleBlock" class="Magento\Theme\Test\Block\Html\Title" locator=".page-title-wrapper" strategy="css selector" />
         <block name="mainBlock" class="Magento\Backend\Test\Block\Page\Main" locator=".dashboard-main" strategy="css selector" />
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/Repository/ConfigData.xml
index fb16b8a6a309d8009f844fc01f2222e4536cf85b..1edc71a3d64465f585ee6e5c74be55248d1e9349 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Repository/ConfigData.xml
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Repository/ConfigData.xml
@@ -248,6 +248,7 @@
                 </item>
             </field>
         </dataset>
+
         <dataset name="custom_allowed_country_rollback">
             <field name="general/country/allow" xsi:type="array">
                 <item name="scope" xsi:type="string">default</item>
@@ -255,6 +256,7 @@
                 <item name="inherit" xsi:type="string">1</item>
             </field>
         </dataset>
+
         <dataset name="enable_single_store_mode">
             <field name="general/single_store_mode/enabled" xsi:type="array">
                 <item name="scope" xsi:type="string">default</item>
@@ -263,6 +265,7 @@
                 <item name="value" xsi:type="number">1</item>
             </field>
         </dataset>
+
         <dataset name="enable_single_store_mode_rollback">
             <field name="general/single_store_mode/enabled" xsi:type="array">
                 <item name="scope" xsi:type="string">default</item>
@@ -271,5 +274,25 @@
                 <item name="value" xsi:type="number">0</item>
             </field>
         </dataset>
+
+        <dataset name="top_destinations_DE_ES_GB">
+            <field name="general/country/destinations" xsi:type="array">
+                <item name="scope" xsi:type="string">default</item>
+                <item name="scope_id" xsi:type="number">0</item>
+                <item name="value" xsi:type="array">
+                    <item name="Germany" xsi:type="string">DE</item>
+                    <item name="Spain" xsi:type="string">ES</item>
+                    <item name="United Kingdom" xsi:type="string">GB</item>
+                </item>
+            </field>
+        </dataset>
+
+        <dataset name="top_destinations_DE_ES_GB_rollback">
+            <field name="general/country/destinations" xsi:type="array">
+                <item name="scope" xsi:type="string">default</item>
+                <item name="scope_id" xsi:type="number">0</item>
+                <item name="value" xsi:type="string"></item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePayPalBraintreeTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePayPalBraintreeTest.php
index 062de338d8921e15b786de0fd4b656e824354d80..ca5fbe8799d5144a2a9e68e7b8fbca4530c26790 100644
--- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePayPalBraintreeTest.php
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePayPalBraintreeTest.php
@@ -33,7 +33,7 @@ class InvoicePayPalBraintreeTest extends Scenario
     /* end tags */
 
     /**
-     * Runs one page checkout test.
+     * Create invoice for order placed within Braintree PayPal.
      *
      * @return void
      */
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePaypalBraintreeTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePaypalBraintreeTest.xml
index 23985d208e5a675b997d330e792eb58f1045d7d9..1d98e2d792a3e75fd815fe78149e43100aad12ae 100644
--- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePaypalBraintreeTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePaypalBraintreeTest.xml
@@ -31,7 +31,7 @@
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderButtonsAvailable" />
             <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceItems" />
         </variation>
-        <variation name="InvoicePayPalBraintreeTestVariation2" summary="Partial capture for order placed within Braintree PayPal" ticketId="MAGETWO-48615">
+        <variation name="InvoicePayPalBraintreeTestVariation2" summary="Partial capture for order placed within Braintree PayPal" ticketId="MAGETWO-48615, MAGETWO-48684">
             <data name="description" xsi:type="string">Partial capture for order placed within Braintree PayPal</data>
             <data name="products/0" xsi:type="string">catalogProductSimple::product_100_dollar</data>
             <data name="taxRule" xsi:type="string">us_illinois_tax_rule</data>
@@ -43,7 +43,6 @@
             </data>
             <data name="capturedPrices" xsi:type="array">
                 <item name="0" xsi:type="string">118.25</item>
-                <item name="1" xsi:type="string">108.25</item>
             </data>
             <data name="payment/method" xsi:type="string">braintree_paypal</data>
             <data name="configData" xsi:type="string">braintree, braintree_paypal, braintree_paypal_skip_order_review</data>
@@ -51,10 +50,18 @@
             <data name="data/items_data/0/qty" xsi:type="string">1</data>
             <data name="data/form_data/do_shipment" xsi:type="string">No</data>
             <data name="data/form_data/comment_text" xsi:type="string">comments</data>
-            <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data>
+            <data name="status" xsi:type="string">Processing</data>
+            <data name="transactions/Capture" xsi:type="array">
+                <item name="transactionType" xsi:type="string">Capture</item>
+                <item name="statusIsClosed" xsi:type="string">No</item>
+            </data>
+            <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data>
             <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceSuccessCreateMessage" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderButtonsAvailable" />
-            <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceItems" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertCaptureInCommentsHistory" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceInInvoicesGrid" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertTransactionStatus" />
         </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Bundle.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Bundle.php
index ccf47420b11521f9f5bf1a6c4b0f347d86c1baa0..042ae16dd2e53353595e478dad6c2d7ce712946e 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Bundle.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Bundle.php
@@ -21,6 +21,20 @@ use Magento\Mtf\Fixture\InjectableFixture;
  */
 class Bundle extends Block
 {
+    /**
+     * Assigned product name.
+     *
+     * @var string
+     */
+    protected $assignedProductName = '.product-name';
+
+    /**
+     * Assigned product price.
+     *
+     * @var string
+     */
+    protected $assignedProductPrice = '.bundle-options-wrapper .price';
+
     /**
      * Selector for single option block
      *
@@ -70,6 +84,20 @@ class Bundle extends Block
      */
     protected $bundleOptionBlock = './/div[label[span[contains(text(), "%s")]]]';
 
+    /**
+     *  Product fixture.
+     *
+     * @var FixtureInterface
+     */
+    private $product;
+
+    /**
+     * Option index.
+     *
+     * @var null|int
+     */
+    protected $optionIndex;
+
     /**
      * Fill bundle option on frontend add click "Add to cart" button
      *
@@ -93,17 +121,19 @@ class Bundle extends Block
     public function getOptions(FixtureInterface $product)
     {
         /** @var BundleProduct  $product */
+        $this->product = $product;
         $bundleSelections = $product->getBundleSelections();
         $bundleOptions = isset($bundleSelections['bundle_options']) ? $bundleSelections['bundle_options'] : [];
 
         $listFormOptions = $this->getListOptions();
         $formOptions = [];
 
-        foreach ($bundleOptions as $option) {
+        foreach ($bundleOptions as $index => $option) {
             $title = $option['title'];
             if (!isset($listFormOptions[$title])) {
                 throw new \Exception("Can't find option: \"{$title}\"");
             }
+            $this->optionIndex = $index;
 
             /** @var SimpleElement $optionElement */
             $optionElement = $listFormOptions[$title];
@@ -118,10 +148,20 @@ class Bundle extends Block
 
             $formOptions[] = $optionData;
         }
-
         return $formOptions;
     }
 
+    /**
+     * Check if bundle option is visible.
+     *
+     * @param string $optionTitle
+     * @return bool
+     */
+    public function isOptionVisible($optionTitle)
+    {
+        return isset($this->getListOptions()[$optionTitle]);
+    }
+
     /**
      * Get list options
      *
@@ -151,6 +191,9 @@ class Bundle extends Block
      */
     protected function getDropdownData(SimpleElement $option)
     {
+        if ($this->isOneProductInStock($this->product)) {
+            return ['options' => $this->getFlatTextData()];
+        }
         $select = $option->find($this->selectOption, Locator::SELECTOR_XPATH, 'select');
         // Skip "Choose option ..."(option #1)
         return $this->getSelectOptionsData($select, 2);
@@ -263,13 +306,16 @@ class Bundle extends Block
     {
         foreach ($bundleOptions as $option) {
             $selector = sprintf($this->bundleOptionBlock, $option['title']);
-            /** @var Option $optionBlock */
-            $optionBlock = $this->blockFactory->create(
-                'Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option\\'
-                . $this->optionNameConvert($option['frontend_type']),
-                ['element' => $this->_rootElement->find($selector, Locator::SELECTOR_XPATH)]
-            );
-            $optionBlock->fillOption($option['value']);
+            $useDefault = isset($option['use_default']) && strtolower($option['use_default']) == 'true' ? true : false;
+            if (!$useDefault) {
+                /** @var Option $optionBlock */
+                $optionBlock = $this->blockFactory->create(
+                    'Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option\\'
+                    . $this->optionNameConvert($option['frontend_type']),
+                    ['element' => $this->_rootElement->find($selector, Locator::SELECTOR_XPATH)]
+                );
+                $optionBlock->fillOption($option['value']);
+            }
         }
     }
 
@@ -284,4 +330,43 @@ class Bundle extends Block
         $trimmedOptionType = preg_replace('/[^a-zA-Z]/', '', $optionType);
         return ucfirst(strtolower($trimmedOptionType));
     }
+
+    /**
+     * Check count products with 'In Stock' status.
+     *
+     * @param BundleProduct $products
+     * @return bool
+     */
+    private function isOneProductInStock(BundleProduct $products)
+    {
+        $result = [];
+        $products = $products->getBundleSelections()['products'][$this->optionIndex];
+        foreach ($products as $product) {
+            $status = $product->getData()['quantity_and_stock_status']['is_in_stock'];
+            if ($status == 'In Stock') {
+                $result[] = $product;
+            }
+        }
+        if (count($result) == 1) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Return list options.
+     *
+     * @return array
+     */
+    private function getFlatTextData()
+    {
+        $productPrice = $this->_rootElement->find($this->assignedProductPrice)->getText();
+        $productPrice = preg_replace("/[^0-9.,]/", '', $productPrice);
+        $productName = $this->_rootElement->find($this->assignedProductName)->getText();
+        $options[$productName] = [
+            'title' => $productName,
+            'price' => number_format($productPrice, 2)
+        ];
+        return $options;
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleItemsOnProductPage.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleItemsOnProductPage.php
index 411c53d982fcb8a2445e8a5d214383670ec7bf4a..930758c50316a66eef00f3a5bea8c812ce519902 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleItemsOnProductPage.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleItemsOnProductPage.php
@@ -65,15 +65,18 @@ class AssertBundleItemsOnProductPage extends AbstractAssertForm
                 'is_require' => $bundleOption['required'],
             ];
 
+            $key = 0;
             foreach ($bundleOption['assigned_products'] as $productKey => $assignedProduct) {
-                $price = isset($assignedProduct['data']['selection_price_value'])
-                    ? $assignedProduct['data']['selection_price_value']
-                    : $bundleSelections['products'][$optionKey][$productKey]->getPrice();
+                if ($this->isInStock($product, $key++)) {
+                    $price = isset($assignedProduct['data']['selection_price_value'])
+                        ? $assignedProduct['data']['selection_price_value']
+                        : $bundleSelections['products'][$optionKey][$productKey]->getPrice();
 
-                $optionData['options'][$productKey] = [
-                    'title' => $assignedProduct['search_data']['name'],
-                    'price' => number_format($price, 2),
-                ];
+                    $optionData['options'][$productKey] = [
+                        'title' => $assignedProduct['search_data']['name'],
+                        'price' => number_format($price, 2),
+                    ];
+                }
             }
 
             $result[$optionKey] = $optionData;
@@ -82,6 +85,24 @@ class AssertBundleItemsOnProductPage extends AbstractAssertForm
         return $result;
     }
 
+    /**
+     * Check product attribute 'is_in_stock'.
+     *
+     * @param BundleProduct $product
+     * @param int $key
+     * @return bool
+     */
+    private function isInStock(BundleProduct $product, $key)
+    {
+        $assignedProducts = $product->getBundleSelections()['products'][0];
+        $status = $assignedProducts[$key]->getData()['quantity_and_stock_status']['is_in_stock'];
+
+        if ($status == 'In Stock') {
+            return true;
+        }
+        return false;
+    }
+
     /**
      * Return Text if displayed on frontend equals with fixture.
      *
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleOptionTitleOnStorefront.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleOptionTitleOnStorefront.php
new file mode 100644
index 0000000000000000000000000000000000000000..cc89daa9d301fa6cdf3f1687576fd2554c6e46ba
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleOptionTitleOnStorefront.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Bundle\Test\Constraint;
+
+use Magento\Catalog\Test\Page\Product\CatalogProductView;
+use Magento\Mtf\Client\BrowserInterface;
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Mtf\Fixture\FixtureInterface;
+use Magento\Cms\Test\Page\CmsIndex;
+
+/**
+ * Assert that option title is correct in different stores on bundle product page.
+ */
+class AssertBundleOptionTitleOnStorefront extends AbstractConstraint
+{
+    /**
+     * Assert that option title is correct on product view page.
+     *
+     * @param CatalogProductView $catalogProductView
+     * @param CmsIndex $cmsIndex
+     * @param BrowserInterface $browser
+     * @param FixtureInterface $originalProduct
+     * @param array $stores
+     * @param array $optionTitles
+     * @return void
+     */
+    public function processAssert(
+        CatalogProductView $catalogProductView,
+        CmsIndex $cmsIndex,
+        BrowserInterface $browser,
+        FixtureInterface $originalProduct,
+        array $stores,
+        array $optionTitles
+    ) {
+        $cmsIndex->open();
+        $cmsIndex->getLinksBlock()->waitWelcomeMessage();
+        foreach ($stores as $store) {
+            $cmsIndex->getStoreSwitcherBlock()->selectStoreView($store->getName());
+            $cmsIndex->getLinksBlock()->waitWelcomeMessage();
+            $browser->open($_ENV['app_frontend_url'] . $originalProduct->getUrlKey() . '.html');
+            $catalogProductView->getBundleViewBlock()->clickCustomize();
+            \PHPUnit_Framework_Assert::assertTrue(
+                $catalogProductView->getBundleViewBlock()->getBundleBlock()->isOptionVisible(
+                    $optionTitles[$store->getStoreId()]
+                ),
+                sprintf(
+                    'Option with title \'%s\' is missing in \'%s\' store view.',
+                    $optionTitles[$store->getStoreId()],
+                    $store->getName()
+                )
+            );
+        }
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Option title is correct on product view page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleProduct/BundleSelections.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleProduct/BundleSelections.php
index f72258c45ad35454be4803c83ccadd6c7dd8f9e7..d98486ffe4646d6664e6c76f7d7bd03d5368b5a7 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleProduct/BundleSelections.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleProduct/BundleSelections.php
@@ -98,4 +98,14 @@ class BundleSelections extends DataSource
             }
         }
     }
+
+    /**
+     * Get products from bundle items.
+     *
+     * @return array
+     */
+    public function getProducts()
+    {
+        return $this->data['products'];
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct.xml
index 25c9e2693258800c04303db31e703247e6507d3f..346c727e6b9f8dfc4963bfc42ee6601587e37ae1 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct.xml
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct.xml
@@ -29,6 +29,28 @@
             </field>
         </dataset>
 
+        <dataset name="default_with_one_simple_product">
+            <field name="name" xsi:type="string">Bundle dynamic product %isolation%</field>
+            <field name="url_key" xsi:type="string">bundle-dynamic-product-%isolation%</field>
+            <field name="sku" xsi:type="string">sku_bundle_dynamic_product_%isolation%</field>
+            <field name="sku_type" xsi:type="string">Yes</field>
+            <field name="price_type" xsi:type="string">Yes</field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="price" xsi:type="array">
+                <item name="dataset" xsi:type="string">bundle_dynamic_with_category</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="bundle_selections" xsi:type="array">
+                <item name="dataset" xsi:type="string">one_simple_product</item>
+            </field>
+        </dataset>
+
         <dataset name="bundle_dynamic_product">
             <field name="name" xsi:type="string">Bundle dynamic product %isolation%</field>
             <field name="sku" xsi:type="string">sku_bundle_dynamic_product_%isolation%</field>
@@ -254,6 +276,47 @@
             </field>
         </dataset>
 
+        <dataset name="bundle_fixed_100_dollar_product_buy_all">
+            <field name="name" xsi:type="string">Bundle fixed product %isolation%</field>
+            <field name="sku" xsi:type="string">sku_bundle_fixed_product_%isolation%</field>
+            <field name="sku_type" xsi:type="string">No</field>
+            <field name="price_type" xsi:type="string">No</field>
+            <field name="price" xsi:type="array">
+                <item name="value" xsi:type="string">100</item>
+                <item name="dataset" xsi:type="string">fixed_100_dollar</item>
+            </field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="weight" xsi:type="string">1</field>
+            <field name="weight_type" xsi:type="string">No</field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="shipment_type" xsi:type="string">Together</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="stock_data" xsi:type="array">
+                <item name="manage_stock" xsi:type="string">Yes</item>
+                <item name="use_config_enable_qty_increments" xsi:type="string">Yes</item>
+                <item name="use_config_qty_increments" xsi:type="string">Yes</item>
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="url_key" xsi:type="string">bundle-fixed-product-%isolation%</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="bundle_selections" xsi:type="array">
+                <item name="dataset" xsi:type="string">fixed_100_dollar_buy_all</item>
+            </field>
+            <field name="attribute_set_id" xsi:type="string">Default</field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">bundle_fixed_100_dollar_buy_all</item>
+            </field>
+        </dataset>
+
         <dataset name="with_3_bundle_options">
             <field name="name" xsi:type="string">Bundle with 3 options %isolation%</field>
             <field name="url_key" xsi:type="string">with_3_bundle_options-%isolation%</field>
@@ -275,5 +338,46 @@
                 <item name="dataset" xsi:type="string">with_3_options</item>
             </field>
         </dataset>
+
+        <dataset name="bundle_low_stock">
+            <field name="name" xsi:type="string">Bundle low stock product %isolation%</field>
+            <field name="sku" xsi:type="string">sku_bundle_low_stock_product_%isolation%</field>
+            <field name="sku_type" xsi:type="string">No</field>
+            <field name="price_type" xsi:type="string">No</field>
+            <field name="price" xsi:type="array">
+                <item name="value" xsi:type="string">750</item>
+                <item name="dataset" xsi:type="string">default_fixed</item>
+            </field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="weight" xsi:type="string">1</field>
+            <field name="weight_type" xsi:type="string">No</field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="shipment_type" xsi:type="string">Together</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="stock_data" xsi:type="array">
+                <item name="manage_stock" xsi:type="string">Yes</item>
+                <item name="use_config_enable_qty_increments" xsi:type="string">Yes</item>
+                <item name="use_config_qty_increments" xsi:type="string">Yes</item>
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="url_key" xsi:type="string">bundle-fixed-product-%isolation%</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="bundle_selections" xsi:type="array">
+                <item name="dataset" xsi:type="string">low_stock_fixed</item>
+            </field>
+            <field name="attribute_set_id" xsi:type="string">Default</field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">bundle_low_stock_fixed</item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/BundleSelections.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/BundleSelections.xml
index a297891ba085ce99ea3391176efa38a8d325e775..8112237bfc31183e9d772dd4df85fdd3ca1e6639 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/BundleSelections.xml
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/BundleSelections.xml
@@ -42,6 +42,31 @@
             </field>
         </dataset>
 
+        <dataset name="one_simple_product">
+            <field name="bundle_options" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="title" xsi:type="string">Drop-down Option</item>
+                    <item name="type" xsi:type="string">Drop-down</item>
+                    <item name="required" xsi:type="string">Yes</item>
+                    <item name="assigned_products" xsi:type="array">
+                        <item name="0" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_qty" xsi:type="string">1</item>
+                            </item>
+                        </item>
+                    </item>
+                </item>
+            </field>
+            <field name="products" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="0" xsi:type="string">catalogProductSimple::default</item>
+                </item>
+            </field>
+        </dataset>
+
         <dataset name="default_fixed">
             <field name="bundle_options" xsi:type="array">
                 <item name="0" xsi:type="array">
@@ -81,6 +106,44 @@
             </field>
         </dataset>
 
+        <dataset name="fixed_with_custom_title">
+            <field name="bundle_options" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="title" xsi:type="string">Custom Option %isolation%</item>
+                    <item name="type" xsi:type="string">Drop-down</item>
+                    <item name="required" xsi:type="string">Yes</item>
+                    <item name="assigned_products" xsi:type="array">
+                        <item name="0" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_price_value" xsi:type="string">5.00</item>
+                                <item name="selection_price_type" xsi:type="string">Fixed</item>
+                                <item name="selection_qty" xsi:type="string">1</item>
+                            </item>
+                        </item>
+                        <item name="1" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_price_value" xsi:type="string">6.00</item>
+                                <item name="selection_price_type" xsi:type="string">Fixed</item>
+                                <item name="selection_qty" xsi:type="string">1</item>
+                            </item>
+                        </item>
+                    </item>
+                </item>
+            </field>
+            <field name="products" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="0" xsi:type="string">catalogProductSimple::default</item>
+                    <item name="1" xsi:type="string">catalogProductSimple::product_100_dollar</item>
+                </item>
+            </field>
+        </dataset>
+
         <dataset name="fixed_100_dollar">
             <field name="bundle_options" xsi:type="array">
                 <item name="0" xsi:type="array">
@@ -120,6 +183,44 @@
             </field>
         </dataset>
 
+        <dataset name="fixed_100_dollar_buy_all">
+            <field name="bundle_options" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="title" xsi:type="string">Drop-down Option</item>
+                    <item name="type" xsi:type="string">Drop-down</item>
+                    <item name="required" xsi:type="string">Yes</item>
+                    <item name="assigned_products" xsi:type="array">
+                        <item name="0" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_price_value" xsi:type="string">10.00</item>
+                                <item name="selection_price_type" xsi:type="string">Fixed</item>
+                                <item name="selection_qty" xsi:type="string">1</item>
+                            </item>
+                        </item>
+                        <item name="1" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_price_value" xsi:type="string">560.00</item>
+                                <item name="selection_price_type" xsi:type="string">Fixed</item>
+                                <item name="selection_qty" xsi:type="string">1</item>
+                            </item>
+                        </item>
+                    </item>
+                </item>
+            </field>
+            <field name="products" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="0" xsi:type="string">catalogProductSimple::default_qty_1</item>
+                    <item name="1" xsi:type="string">catalogProductSimple::out_of_stock</item>
+                </item>
+            </field>
+        </dataset>
+
         <dataset name="second">
             <field name="bundle_options" xsi:type="array">
                 <item name="0" xsi:type="array">
@@ -927,5 +1028,43 @@
                 </item>
             </field>
         </dataset>
+
+        <dataset name="low_stock_fixed">
+            <field name="bundle_options" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="title" xsi:type="string">Drop-down Option</item>
+                    <item name="type" xsi:type="string">Drop-down</item>
+                    <item name="required" xsi:type="string">Yes</item>
+                    <item name="assigned_products" xsi:type="array">
+                        <item name="0" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_price_value" xsi:type="string">5.00</item>
+                                <item name="selection_price_type" xsi:type="string">Fixed</item>
+                                <item name="selection_qty" xsi:type="string">1</item>
+                            </item>
+                        </item>
+                        <item name="1" xsi:type="array">
+                            <item name="search_data" xsi:type="array">
+                                <item name="name" xsi:type="string">%product_name%</item>
+                            </item>
+                            <item name="data" xsi:type="array">
+                                <item name="selection_price_value" xsi:type="string">6.00</item>
+                                <item name="selection_price_type" xsi:type="string">Fixed</item>
+                                <item name="selection_qty" xsi:type="string">1</item>
+                            </item>
+                        </item>
+                    </item>
+                </item>
+            </field>
+            <field name="products" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="0" xsi:type="string">catalogProductSimple::default</item>
+                    <item name="1" xsi:type="string">catalogProductSimple::low_stock_product</item>
+                </item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/CheckoutData.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/CheckoutData.xml
index e694b65110e89cd1840ad1249e6c14a61302a877..8a17e1b9de596b0f5063a4785f90abeebea22e5a 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/CheckoutData.xml
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/CheckoutData.xml
@@ -85,6 +85,27 @@
             </field>
         </dataset>
 
+        <dataset name="bundle_fixed_100_dollar_buy_all">
+            <field name="options" xsi:type="array">
+                <item name="bundle_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">Drop-down Option</item>
+                        <item name="type" xsi:type="string">Drop-down</item>
+                        <item name="use_default" xsi:type="string">true</item>
+                        <item name="value" xsi:type="array">
+                            <item name="name" xsi:type="string">default_qty_1</item>
+                        </item>
+                    </item>
+                </item>
+            </field>
+            <field name="qty" xsi:type="string">1</field>
+            <field name="cartItem" xsi:type="array">
+                <item name="price" xsi:type="string">110</item>
+                <item name="qty" xsi:type="string">1</item>
+                <item name="subtotal" xsi:type="string">110</item>
+            </field>
+        </dataset>
+
         <dataset name="bundle_update_mini_shopping_cart">
             <field name="options" xsi:type="array">
                 <item name="bundle_options" xsi:type="array">
@@ -396,6 +417,26 @@
             </field>
         </dataset>
 
+        <dataset name="bundle_low_stock_fixed">
+            <field name="options" xsi:type="array">
+                <item name="bundle_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">Drop-down Option</item>
+                        <item name="type" xsi:type="string">Drop-down</item>
+                        <item name="value" xsi:type="array">
+                            <item name="name" xsi:type="string">low_stock_product</item>
+                        </item>
+                    </item>
+                </item>
+            </field>
+            <field name="qty" xsi:type="string">1</field>
+            <field name="cartItem" xsi:type="array">
+                <item name="price" xsi:type="string">756</item>
+                <item name="qty" xsi:type="string">1</item>
+                <item name="subtotal" xsi:type="string">756</item>
+            </field>
+        </dataset>
+
         <dataset name="bundle_required_three_fixed_options_with_qty">
             <field name="options" xsi:type="array">
                 <item name="bundle_options" xsi:type="array">
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 56b2ceb917fe6d46296e408954bdfc88380af5a3..98f7ac4b0cdbd9a25e33f6e7ef0a450df34bbdae 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
@@ -74,8 +74,7 @@
             <constraint name="Magento\Bundle\Test\Constraint\AssertBundlePriceView" />
             <constraint name="Magento\Bundle\Test\Constraint\AssertBundlePriceType" />
         </variation>
-        <variation name="CreateBundleProductEntityTestVariation4">
-            <data name="tag" xsi:type="string">stable:no</data>
+        <variation name="CreateBundleProductEntityTestVariation4" summary="Create bundle product with out of stock simple product" ticketId="MAGETWO-12801">
             <data name="description" xsi:type="string">Create fixed bundle</data>
             <data name="product/data/url_key" xsi:type="string">bundle-product-%isolation%</data>
             <data name="product/data/name" xsi:type="string">BundleProduct %isolation%</data>
@@ -89,7 +88,7 @@
             <data name="product/data/weight" xsi:type="string">10</data>
             <data name="product/data/description" xsi:type="string">Bundle Product Fixed Required</data>
             <data name="product/data/bundle_selections/dataset" xsi:type="string">default_fixed</data>
-            <data name="product/data/bundle_selections/products" xsi:type="string">catalogProductSimple::product_100_dollar,catalogProductVirtual::product_50_dollar</data>
+            <data name="product/data/bundle_selections/products" xsi:type="string">catalogProductSimple::product_100_dollar,catalogProductSimple::out_of_stock</data>
             <data name="product/data/checkout_data/dataset" xsi:type="string">bundle_default</data>
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductInGrid" />
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleProductEntityTest.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleProductEntityTest.php
index 8326b1ba4d9ae9b0589b1d55bd973f9db6efe970..a8b0f49f030c1bccc5ce6c0aa5dfe38aff785b1d 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleProductEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleProductEntityTest.php
@@ -7,9 +7,11 @@
 namespace Magento\Bundle\Test\TestCase;
 
 use Magento\Bundle\Test\Fixture\BundleProduct;
+use Magento\Store\Test\Fixture\Store;
 use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
 use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
 use Magento\Mtf\TestCase\Injectable;
+use Magento\Mtf\Fixture\FixtureFactory;
 
 /**
  * Test Flow:
@@ -50,47 +52,84 @@ class UpdateBundleProductEntityTest extends Injectable
     protected $catalogProductEdit;
 
     /**
-     * Injection data
+     * Fixture Factory.
+     *
+     * @var FixtureFactory
+     */
+    private $fixtureFactory;
+
+    /**
+     * Injection data.
      *
      * @param CatalogProductIndex $catalogProductIndexNewPage
      * @param CatalogProductEdit $catalogProductEditPage
+     * @param FixtureFactory $fixtureFactory
      * @return void
      */
     public function __inject(
         CatalogProductIndex $catalogProductIndexNewPage,
-        CatalogProductEdit $catalogProductEditPage
+        CatalogProductEdit $catalogProductEditPage,
+        FixtureFactory $fixtureFactory
     ) {
         $this->catalogProductIndex = $catalogProductIndexNewPage;
         $this->catalogProductEdit = $catalogProductEditPage;
+        $this->fixtureFactory = $fixtureFactory;
     }
 
     /**
-     * Test update bundle product
+     * Test update bundle product.
      *
      * @param BundleProduct $product
      * @param BundleProduct $originalProduct
+     * @param Store|null $store
      * @return array
      */
-    public function test(BundleProduct $product, BundleProduct $originalProduct)
-    {
-        $this->markTestIncomplete('MAGETWO-56584: [FT] Custom options are not created for product in test');
+    public function test(
+        BundleProduct $product,
+        BundleProduct $originalProduct,
+        Store $store = null
+    ) {
         // Preconditions
         $originalProduct->persist();
-        $originalCategory = $originalProduct->hasData('category_ids')
-            ? $originalProduct->getDataFieldConfig('category_ids')['source']->getCategories()
-            : null;
-        $category = $product->hasData('category_ids')
-            ? $product->getDataFieldConfig('category_ids')['source']->getCategories()
-            : $originalCategory;
+        $category = $this->getCategories($originalProduct, $product);
+
+        if ($store) {
+            $store->persist();
+            $optionTitle[$store->getStoreId()] = $product->getBundleSelections()['bundle_options'][0]['title'];
+        }
 
         // Steps
         $filter = ['sku' => $originalProduct->getSku()];
 
         $this->catalogProductIndex->open();
         $this->catalogProductIndex->getProductGrid()->searchAndOpen($filter);
+        if ($store) {
+            $this->catalogProductEdit->getFormPageActions()->changeStoreViewScope($store);
+        }
         $this->catalogProductEdit->getProductForm()->fill($product);
         $this->catalogProductEdit->getFormPageActions()->save();
 
-        return ['category' => $category];
+        return [
+            'category' => $category,
+            'stores' => isset($store) ? [$store] : [],
+            'optionTitles' => isset($optionTitle) ? $optionTitle : []
+        ];
+    }
+
+    /**
+     * Get Category instances.
+     *
+     * @param BundleProduct $originalProduct
+     * @param BundleProduct $product
+     * @return array
+     */
+    protected function getCategories(BundleProduct $originalProduct, BundleProduct $product)
+    {
+        $originalCategory = $originalProduct->hasData('category_ids')
+            ? $originalProduct->getDataFieldConfig('category_ids')['source']->getCategories()
+            : null;
+        return $product->hasData('category_ids')
+            ? $product->getDataFieldConfig('category_ids')['source']->getCategories()
+            : $originalCategory;
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleProductEntityTest.xml
index e4f567de39481249ca083398152f237c35b3c2cf..958e074b91b8694153caa9df7f56cad4df87f310 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleProductEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleProductEntityTest.xml
@@ -83,5 +83,12 @@
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" />
             <constraint name="Magento\Bundle\Test\Constraint\AssertBundleProductPage" />
         </variation>
+        <variation name="UpdateBundleProductEntityTestVariation6" summary="Verify data overrirding on Store View level" ticketId="MAGETWO-50642">
+            <data name="originalProduct/dataset" xsi:type="string">bundle_fixed_product</data>
+            <data name="store/dataset" xsi:type="string">custom</data>
+            <data name="product/data/bundle_selections/dataset" xsi:type="string">fixed_with_custom_title</data>
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" />
+            <constraint name="Magento\Bundle\Test\Constraint\AssertBundleOptionTitleOnStorefront" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/PageActions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/PageActions.php
index 808da58c7dd4995a20f88ef2059df2ecc9eb574f..73a5f73a47e29df8dcc175a62d875a79d2d72b7d 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/PageActions.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/PageActions.php
@@ -17,7 +17,7 @@ class PageActions extends FormPageActions
     /**
      * Top page element to implement a scrolling in case of floating blocks overlay.
      */
-    const TOP_ELEMENT_TO_SCROLL = '.page-title';
+    const TOP_ELEMENT_TO_SCROLL = 'header.page-header';
 
     /**
      * Locator for "OK" button in warning block
@@ -62,7 +62,7 @@ class PageActions extends FormPageActions
      */
     public function selectStoreView($name)
     {
-        $this->browser->find(self::TOP_ELEMENT_TO_SCROLL)->click();
+        $this->browser->find(self::TOP_ELEMENT_TO_SCROLL)->hover();
         $this->_rootElement->find($this->storeChangeButton)->click();
         $this->waitForElementVisible($name, Locator::SELECTOR_LINK_TEXT);
         $this->_rootElement->find($name, Locator::SELECTOR_LINK_TEXT)->click();
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Tree.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Tree.php
index 447e1319898084dfecbcb50e3f801ae04ae9f156..6a89b1ab5fdd81dbed7f956070cd5d7c6888be79 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Tree.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Tree.php
@@ -176,6 +176,7 @@ class Tree extends Block
             sprintf($this->categoryInTree, $parentCategoryName),
             Locator::SELECTOR_XPATH
         );
+        $targetElement->hover();
         $this->_rootElement->find(sprintf($this->categoryInTree, $childCategoryName), Locator::SELECTOR_XPATH)
             ->dragAndDrop($targetElement);
     }
@@ -185,7 +186,7 @@ class Tree extends Block
      *
      * @return void
      */
-    protected function expandAllCategories()
+    public function expandAllCategories()
     {
         $this->_rootElement->find($this->expandAll)->click();
     }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Grid.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Grid.php
index 8f64af8ac0900460a77ce158ea26e24bfe022911..db078d4500d47776fba597bef437ccd4093d58cb 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Grid.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Grid.php
@@ -15,14 +15,14 @@ use Magento\Backend\Test\Block\Widget\Grid as AbstractGrid;
 class Grid extends AbstractGrid
 {
     /**
-     * Locator value for link in action column
+     * Locator value for link in action column.
      *
      * @var string
      */
     protected $editLink = 'td.col-frontend_label';
 
     /**
-     * Filters array mapping
+     * Filters array mapping.
      *
      * @var array
      */
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/ProductDetails/CategoryIds.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/ProductDetails/CategoryIds.php
index 371186cea6c54147e1c5105397c04a1c714df9b3..b9c4e30605cb8bdf2616e0393d4388a6bfbd7ceb 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/ProductDetails/CategoryIds.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/ProductDetails/CategoryIds.php
@@ -68,16 +68,32 @@ class CategoryIds extends MultisuggestElement
     /**
      * Set category value.
      *
-     * @param array|string $value
+     * @param array|string $values
      * @return void
      */
-    public function setValue($value)
+    public function setValue($values)
     {
         // Align Category ids select element to the center of the browser for created categories
         if ($this->browser->find($this->pageFooter)->isVisible()) {
             $this->browser->find($this->pageFooter)->hover();
             $this->browser->find($this->advancedInventoryButton)->hover();
         }
-        parent::setValue($value);
+        $this->eventManager->dispatchEvent(['set_value'], [__METHOD__, $this->getAbsoluteSelector()]);
+
+        $this->clear();
+        foreach ((array)$values as $value) {
+            if (!$this->isChoice($value)) {
+                if ($value == '') {
+                    continue;
+                }
+                $this->keys([$value]);
+                $searchedItem = $this->find(sprintf($this->resultItem, $value), Locator::SELECTOR_XPATH);
+                $searchedItem->click();
+                $closeButton = $this->find($this->closeButton);
+                if ($closeButton->isVisible()) {
+                    $closeButton->click();
+                }
+            }
+        }
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/FormPageActions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/FormPageActions.php
index decc7996a7e1e7e97c46fb5d711deb7005dd4bcc..2b83cd83009787f5994ba53eaa5dd5e78eb46d1b 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/FormPageActions.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/FormPageActions.php
@@ -58,6 +58,27 @@ class FormPageActions extends ParentFormPageActions
      */
     private $addAttribute = '[data-ui-id="addattribute-button"]';
 
+    /**
+     * Default store switcher block locator.
+     *
+     * @var string
+     */
+    private $storeSwitcherBlock = '.store-switcher';
+
+    /**
+     * Dropdown block locator.
+     *
+     * @var string
+     */
+    private $dropdownBlock = '.dropdown';
+
+    /**
+     * Selector for confirm.
+     *
+     * @var string
+     */
+    private $confirmModal = '.confirm._show[data-role=modal]';
+
     /**
      * Click on "Save" button.
      *
@@ -122,4 +143,26 @@ class FormPageActions extends ParentFormPageActions
     {
         $this->_rootElement->find($this->addAttribute)->click();
     }
+
+    /**
+     * Change Store View scope.
+     *
+     * @param FixtureInterface $store
+     * @return void
+     */
+    public function changeStoreViewScope(FixtureInterface $store)
+    {
+        $this->waitForElementNotVisible($this->spinner);
+        $this->waitForElementVisible($this->storeSwitcherBlock);
+        $this->_rootElement->find($this->storeSwitcherBlock)
+            ->find($this->dropdownBlock, Locator::SELECTOR_CSS, 'liselectstore')
+            ->setValue(sprintf('%s/%s', $store->getGroupId(), $store->getName()));
+        $modalElement = $this->browser->find($this->confirmModal);
+        /** @var \Magento\Ui\Test\Block\Adminhtml\Modal $modal */
+        $modal = $this->blockFactory->create(
+            \Magento\Ui\Test\Block\Adminhtml\Modal::class,
+            ['element' => $modalElement]
+        );
+        $modal->acceptAlert();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php
index 08d38f45c4ff99a4eae99a1be3c3972bdba7f790..4ef9203827bbc6180b07c4d6f85814dd5f33581f 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php
@@ -96,13 +96,17 @@ class ProductForm extends FormSections
             $this->callRender($typeId, 'fill', $renderArguments);
         } else {
             $sections = $this->getFixtureFieldsByContainers($product);
-            $category = $product->hasData('category_ids')
-                ? $product->getDataFieldConfig('category_ids')['source']->getCategories()[0] : $category;
-            if ($category) {
-                if ((int)$category->getId()) {
-                    $sections['product-details']['category_ids']['value'] = $category->getName();
-                } else {
-                    $this->getNewCategoryModalForm()->addNewCategory($category);
+            if ($product->hasData('category_ids') || $category) {
+                $sections['product-details']['category_ids']['value'] = [];
+                $categories = $product->hasData('category_ids')
+                    ? $product->getDataFieldConfig('category_ids')['source']->getCategories()
+                    : [$category];
+                foreach ($categories as $category) {
+                    if ((int)$category->getId()) {
+                        $sections['product-details']['category_ids']['value'][] = $category->getName();
+                    } else {
+                        $this->getNewCategoryModalForm()->addNewCategory($category);
+                    }
                 }
             }
             $this->fillContainers($sections, $element);
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml
index 3b66164ebe658097e05fdba2e8b53c6cb3d643d2..7e5070e4f154f5fc284b8b6805c19689a5fc2337 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml
@@ -53,6 +53,10 @@
             <country_of_manufacture>
                 <input>select</input>
             </country_of_manufacture>
+            <use_default_name>
+                <selector>[name="use_default[name]"]</selector>
+                <input>checkbox</input>
+            </use_default_name>
         </fields>
     </product-details>
     <advanced-pricing>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ListProduct.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ListProduct.php
index 2584f437bff755322c5033b50545d4c290457087..7c957a6d584b5630176fcc508598087e1f078ac9 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ListProduct.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/ListProduct.php
@@ -77,6 +77,11 @@ class ListProduct extends Block
      */
     public function getSortByValues()
     {
-        return explode("\n", $this->_rootElement->find($this->sorter)->getText());
+        $values = explode("\n", $this->_rootElement->find($this->sorter)->getText());
+        $result = [];
+        foreach ($values as $value) {
+            $result[] = trim($value);
+        }
+        return $result;
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Search.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Search.php
index 2fe1fecc99333986ef5a9146ff86f34d3e627f67..2e66a1c15f833e2bb07680460f685cdd59e81c11 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Search.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Search.php
@@ -68,12 +68,14 @@ class Search extends Block
      * Perform search by a keyword.
      *
      * @param string $keyword
+     * @param string|null $length
      * @return void
-     *
-     * @SuppressWarnings(PHPMD.ConstructorWithNameAsEnclosingClass)
      */
-    public function search($keyword)
+    public function search($keyword, $length = null)
     {
+        if ($length) {
+            $keyword = substr($keyword, 0, $length);
+        }
         $this->fillSearch($keyword);
         $this->_rootElement->find($this->searchButton)->click();
     }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryMovedMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryMovedMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..3f2a84a91a7f5cc88259ed9912d8619e336884b6
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryMovedMessage.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Magento\Catalog\Test\Page\Adminhtml\CatalogCategoryEdit;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that success message is displayed after category moving.
+ */
+class AssertCategoryMovedMessage extends AbstractConstraint
+{
+    /**
+     * Success category save message.
+     */
+    const SUCCESS_MESSAGE = 'You moved the category.';
+
+    /**
+     * Assert that success message is displayed after category moving.
+     *
+     * @param CatalogCategoryEdit $catalogCategoryEdit
+     * @return void
+     */
+    public function processAssert(CatalogCategoryEdit $catalogCategoryEdit)
+    {
+        $actualMessage = $catalogCategoryEdit->getMessagesBlock()->getSuccessMessage();
+        \PHPUnit_Framework_Assert::assertEquals(
+            self::SUCCESS_MESSAGE,
+            $actualMessage,
+            'Wrong success message is displayed.'
+            . "\nExpected: " . self::SUCCESS_MESSAGE
+            . "\nActual: " . $actualMessage
+        );
+    }
+
+    /**
+     * Success message is displayed.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Success message is displayed.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryOnCustomWebsite.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryOnCustomWebsite.php
new file mode 100644
index 0000000000000000000000000000000000000000..e3868b86372d6d3add02b06a29d0056171f67221
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryOnCustomWebsite.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Magento\Catalog\Test\Fixture\Category;
+use Magento\Catalog\Test\Page\Category\CatalogCategoryView;
+use Magento\Mtf\Client\BrowserInterface;
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Mtf\Fixture\FixtureFactory;
+
+/**
+ * Assert category name on custom website store.
+ */
+class AssertCategoryOnCustomWebsite extends AbstractConstraint
+{
+    /**
+     * Assert that category name is correct on custom website store.
+     *
+     * @param FixtureFactory $fixtureFactory
+     * @param BrowserInterface $browser
+     * @param CatalogCategoryView $categoryView
+     * @param Category $category
+     * @return void
+     */
+    public function processAssert(
+        FixtureFactory $fixtureFactory,
+        BrowserInterface $browser,
+        CatalogCategoryView $categoryView,
+        Category $category
+    ) {
+        $storeGroup = $fixtureFactory->createByCode(
+            'storeGroup',
+            [
+                'dataset' => 'custom_new_group',
+                'data' => [
+                    'root_category_id' => [
+                        'category' => $category->getDataFieldConfig('parent_id')['source']->getParentCategory()
+                    ]
+                ]
+            ]
+        );
+        $storeGroup->persist();
+        $store = $fixtureFactory->createByCode(
+            'store',
+            [
+                'dataset' => 'custom_store',
+                'data' => [
+                    'group_id' => [
+                        'storeGroup' => $storeGroup
+                    ]
+                ]
+            ]
+        );
+        $store->persist();
+
+        $websiteCode = $storeGroup->getDataFieldConfig('website_id')['source']->getWebsite()->getData('code');
+        $browser->open($_ENV['app_frontend_url'] . 'websites/' . $websiteCode . '/' . $category->getName() . '.html');
+        \PHPUnit_Framework_Assert::assertEquals(
+            $category->getName(),
+            $categoryView->getTitleBlock()->getTitle(),
+            'Wrong category name is displayed on custom website store.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Category name is correct on custom website store.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductNameOnDifferentStoreViews.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductNameOnDifferentStoreViews.php
new file mode 100644
index 0000000000000000000000000000000000000000..bf3fe9911d331037f0501b77778451d08deb0cbf
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductNameOnDifferentStoreViews.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Magento\Catalog\Test\Page\Product\CatalogProductView;
+use Magento\Mtf\Client\BrowserInterface;
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Mtf\Fixture\FixtureInterface;
+use Magento\Cms\Test\Page\CmsIndex;
+
+/**
+ * Assert product name in different store views on product view page.
+ */
+class AssertProductNameOnDifferentStoreViews extends AbstractConstraint
+{
+    /**
+     * Assert that product name is correct on the storefront in different store views.
+     *
+     * @param CatalogProductView $catalogProductView
+     * @param CmsIndex $cmsIndex
+     * @param BrowserInterface $browser
+     * @param FixtureInterface $initialProduct
+     * @param array $stores
+     * @param array $productNames
+     * @return void
+     */
+    public function processAssert(
+        CatalogProductView $catalogProductView,
+        CmsIndex $cmsIndex,
+        BrowserInterface $browser,
+        FixtureInterface $initialProduct,
+        array $stores,
+        array $productNames
+    ) {
+        $browser->open($_ENV['app_frontend_url'] . $initialProduct->getUrlKey() . '.html');
+        foreach ($stores as $store) {
+            $cmsIndex->getStoreSwitcherBlock()->selectStoreView($store->getName());
+            $cmsIndex->getLinksBlock()->waitWelcomeMessage();
+            \PHPUnit_Framework_Assert::assertEquals(
+                $productNames[$store->getStoreId()],
+                $catalogProductView->getViewBlock()->getProductName(),
+                sprintf('Wrong product name is displayed for %s store view.', $store->getName())
+            );
+        }
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Product name is correct on the storefront';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSaveMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSaveMessage.php
index 5813850ef45d49ece29518a13f4a9f1d0f9059cf..8bfcb394a1fdfa761592dd803925be9b8ce44b86 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSaveMessage.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSaveMessage.php
@@ -15,12 +15,12 @@ use Magento\Mtf\Constraint\AbstractConstraint;
 class AssertProductSaveMessage extends AbstractConstraint
 {
     /**
-     * Text value to be checked
+     * Text value to be checked.
      */
     const SUCCESS_MESSAGE = 'You saved the product.';
 
     /**
-     * Assert that success message is displayed after product save
+     * Assert that success message is displayed after product save.
      *
      * @param CatalogProductEdit $productPage
      * @return void
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml
index e8ceb1d0889247805746a401f6c60bb5a0556010..f37ba686ae6889b0e16dbf17a64f812ae5a32b0d 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml
@@ -47,6 +47,7 @@
         <field name="msrp" is_required="0" />
         <field name="msrp_display_actual_price_type" is_required="0" />
         <field name="name" is_required="1" group="product-details" />
+        <field name="use_default_name" group="product-details" />
         <field name="old_id" is_required="0" />
         <field name="options_container" is_required="0" />
         <field name="page_layout" is_required="0" />
@@ -70,6 +71,7 @@
         <field name="url_path" is_required="0" />
         <field name="visibility" is_required="0" group="product-details" />
         <field name="weight" is_required="0" group="product-details" />
+        <field name="additional_attributes" is_required="0" group="product-details" />
         <field name="id" group="null" />
         <field name="type_id" />
         <field name="attribute_set_id" group="product-details" source="Magento\Catalog\Test\Fixture\Product\AttributeSetId" />
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Category/CategoryProducts.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Category/CategoryProducts.php
index aa3f2138fbe417bd40cfe78750349631359884b0..5c1093ad953e49a38fd125d3a84dd543e8377d7b 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Category/CategoryProducts.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Category/CategoryProducts.php
@@ -33,18 +33,24 @@ class CategoryProducts extends DataSource
         if (!empty($data['dataset']) && $data['dataset'] !== '-') {
             $dataset = array_map('trim', explode(',', $data['dataset']));
             foreach ($dataset as $value) {
-                $explodeValue = explode('::', $value);
-                $product = $fixtureFactory->createByCode($explodeValue[0], ['dataset' => $explodeValue[1]]);
-                if (!$product->getId()) {
-                    $product->persist();
-                }
-                $this->data[] = $product->getName();
+                list($fixtureCode, $dataset) = explode('::', $value);
+                $this->products[] = $fixtureFactory->createByCode($fixtureCode, ['dataset' => $dataset]);
+            }
+        }
+        if (isset($data['products'])) {
+            foreach ($data['products'] as $product) {
                 $this->products[] = $product;
             }
         }
+        foreach ($this->products as $product) {
+            if (!$product->hasData('id')) {
+                $product->persist();
+            }
+            $this->data[] = $product->getName();
+        }
     }
 
-    /**
+    /**\
      * Return products.
      *
      * @return array
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/CategoryIds.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/CategoryIds.php
index d7984dceb7bced436f2c0cf2939b301226adb60a..bb011b3bc26c9fed9ae8967f27a068c76048deb7 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/CategoryIds.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/CategoryIds.php
@@ -51,11 +51,7 @@ class CategoryIds extends DataSource
         } elseif (isset($data['dataset'])) {
             $datasets = explode(',', $data['dataset']);
             foreach ($datasets as $dataset) {
-                if (trim($dataset) == '-') {
-                    $this->data[] = '';
-                    continue;
-                }
-                $category = $fixtureFactory->createByCode('category', ['dataset' => $dataset]);
+                $category = $fixtureFactory->createByCode('category', ['dataset' => trim($dataset)]);
                 if (!isset($data['new_category']) || $data['new_category'] !== 'yes') {
                     $category->persist();
                 }
@@ -64,6 +60,16 @@ class CategoryIds extends DataSource
                 $this->data[] = $category->getName();
                 $this->categories[] = $category;
             }
+        } else {
+            foreach ($data as $category) {
+                if ($category instanceof Category) {
+                    if (!$category->hasData('id')) {
+                        $category->persist();
+                    }
+                    $this->data[] = $category->getName();
+                    $this->categories[] = $category;
+                }
+            }
         }
     }
 
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/WebsiteIds.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/WebsiteIds.php
index 04c06e5eade843529b5767034dc0db18bc8fdb21..56c9499ea1a93aac1d9e680dd5e9ceb2ce39b6bc 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/WebsiteIds.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/WebsiteIds.php
@@ -8,6 +8,7 @@ namespace Magento\Catalog\Test\Fixture\Product;
 
 use Magento\Mtf\Fixture\DataSource;
 use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Store\Test\Fixture\Store;
 
 /**
  * Prepare websites.
@@ -72,25 +73,39 @@ class WebsiteIds extends DataSource
         }
 
         foreach ($this->fixtureData as $dataset) {
-            if (isset($dataset['dataset'])) {
+            if (is_array($dataset) && isset($dataset['dataset'])) {
                 $store = $this->fixtureFactory->createByCode('store', $dataset);
-
-                if (!$store->getStoreId()) {
-                    $store->persist();
+                $this->processStore($store);
+            } elseif ($dataset instanceof Store) {
+                $this->processStore($dataset);
+            } elseif (isset($dataset['websites'])) {
+                foreach ($dataset['websites'] as $website) {
+                    $this->websites[] = $website;
                 }
-
-                $website = $store->getDataFieldConfig('group_id')['source']
-                    ->getStoreGroup()->getDataFieldConfig('website_id')['source']->getWebsite();
-
-                $this->data[] = $website->getName();
-                $this->websites[] = $website;
-                $this->stores[] = $store;
             }
         }
 
         return parent::getData($key);
     }
 
+    /**
+     * Add website by store fixture.
+     *
+     * @param Store $store
+     * @return void
+     */
+    private function processStore(Store $store)
+    {
+        if (!$store->getStoreId()) {
+            $store->persist();
+        }
+        $website = $store->getDataFieldConfig('group_id')['source']
+            ->getStoreGroup()->getDataFieldConfig('website_id')['source']->getWebsite();
+        $this->data[] = $website->getName();
+        $this->websites[] = $website;
+        $this->stores[] = $store;
+    }
+
     /**
      * Return stores.
      *
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductAttribute/Curl.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductAttribute/Curl.php
index db43cc535ca01c4bbac96e425a435bd71ef3fcef..ddf036fd18abb1cc0c964abf7685eeaed6208a0c 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductAttribute/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductAttribute/Curl.php
@@ -17,6 +17,20 @@ use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
  */
 class Curl extends AbstractCurl implements CatalogProductAttributeInterface
 {
+    /**
+     * Relative action path with parameters.
+     *
+     * @var string
+     */
+    protected $urlActionPath = 'catalog/product_attribute/save/back/edit';
+
+    /**
+     * Message for Exception when was received not successful response.
+     *
+     * @var string
+     */
+    protected $responseExceptionMessage = 'Product Attribute creating by curl handler was not successful!';
+
     /**
      * Mapping values for data.
      *
@@ -85,14 +99,15 @@ class Curl extends AbstractCurl implements CatalogProductAttributeInterface
         }
 
         $data = $this->changeStructureOfTheData($data);
-        $url = $_ENV['app_backend_url'] . 'catalog/product_attribute/save/back/edit';
+        $url = $_ENV['app_backend_url'] . $this->urlActionPath;
         $curl = new BackendDecorator(new CurlTransport(), $this->_configuration);
         $curl->write($url, $data);
         $response = $curl->read();
         $curl->close();
 
         if (!strpos($response, 'data-ui-id="messages-message-success"')) {
-            throw new \Exception("Product Attribute creating by curl handler was not successful! \n" . $response);
+            $this->_eventManager->dispatchEvent(['curl_failed'], [$response]);
+            throw new \Exception($this->responseExceptionMessage);
         }
 
         $resultData = [];
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php
index 2ccb804b073f90255f378a6e3ef6e8af5d427332..9267d041d6a1800352acc7cdf6b76392c21d4ce8 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php
@@ -488,7 +488,6 @@ class Curl extends AbstractCurl implements CatalogProductSimpleInterface
         if (!isset($this->fields['product']['custom_options'])) {
             return;
         }
-
         $options = [];
         foreach ($this->fields['product']['custom_options'] as $key => $customOption) {
             $options[$key] = [
@@ -510,7 +509,7 @@ class Curl extends AbstractCurl implements CatalogProductSimpleInterface
         }
 
         $this->fields['product']['options'] = $options;
-        $this->fields['affect_product_custom_options'] = 1;
+        $this->fields['product']['affect_product_custom_options'] = 1;
         unset($this->fields['product']['custom_options']);
     }
 
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogCategoryEdit.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogCategoryEdit.xml
index c44aa5e05de56affdc3bac97eed1a2df0ad2762c..9a4500ed5b0d7f3c625c4fc855919ccb80700df8 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogCategoryEdit.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogCategoryEdit.xml
@@ -7,7 +7,7 @@
  -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/pages.xsd">
     <page name="CatalogCategoryEdit" area="Adminhtml" mca="catalog/category/edit" module="Magento_Catalog">
-        <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator="#messages" strategy="css selector"/>
+        <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator="#messages, .messages" strategy="css selector"/>
         <block name="formPageActions" class="Magento\Catalog\Test\Block\Adminhtml\Category\Edit\PageActions" locator=".page-main-actions" strategy="css selector"/>
         <block name="editForm" class="Magento\Catalog\Test\Block\Adminhtml\Category\Edit\CategoryForm" locator="#container" strategy="css selector"/>
         <block name="modalBlock" class="Magento\Ui\Test\Block\Adminhtml\Modal" locator="._show[data-role=modal]" strategy="css selector"/>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.xml
index 2b27b6ac3c108e6c1bd694627a1b20195c845b24..8c7180da376d361c16ba279416b91c6bcd868da4 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.xml
@@ -15,5 +15,6 @@
         <block name="listProductBlock" class="Magento\Catalog\Test\Block\Product\ListProduct" locator=".products.wrapper.grid" strategy="css selector"/>
         <block name="topToolbar" class="Magento\Catalog\Test\Block\Product\ProductList\TopToolbar" locator=".//*[contains(@class,'toolbar-products')][1]" strategy="xpath"/>
         <block name="bottomToolbar" class="Magento\Catalog\Test\Block\Product\ProductList\BottomToolbar" locator=".//*[contains(@class,'toolbar-products')][2]" strategy="xpath"/>
+        <block name="messagesBlock" class="Magento\Cms\Test\Block\Messages" locator=".page.messages" strategy="css selector" />
     </page>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogAttributeSet.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogAttributeSet.xml
index a62bef0680a9eaf1eff6adf99f809e3f9c538353..82fd8283da0e161845f0500ea3c9a623663bbd93 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogAttributeSet.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogAttributeSet.xml
@@ -38,5 +38,15 @@
                 <item name="dataset" xsi:type="string">color_for_promo_rules</item>
             </field>
         </dataset>
+
+        <dataset name="custom_attribute_set_with_sizes">
+            <field name="attribute_set_name" xsi:type="string">Custom_attribute_set_with_sizes_%isolation%</field>
+            <field name="skeleton_set" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="assigned_attributes" xsi:type="array">
+                <item name="dataset" xsi:type="string">sizes_for_promo_rules</item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml
index e94af12754af5615b48c81f37fe2a3df21470eff..8182177ed56db24329b38e9b0342bfdeb374732a 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml
@@ -204,5 +204,55 @@
                 </item>
             </field>
         </dataset>
+
+        <dataset name="sizes_S_M_L">
+            <field name="frontend_label" xsi:type="string">size_%isolation%</field>
+            <field name="attribute_code" xsi:type="string">size_%isolation%</field>
+            <field name="frontend_input" xsi:type="string">Dropdown</field>
+            <field name="is_required" xsi:type="string">No</field>
+            <field name="options" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="is_default" xsi:type="string">No</item>
+                    <item name="admin" xsi:type="string">SIZE_S</item>
+                    <item name="view" xsi:type="string">SIZE_S</item>
+                </item>
+                <item name="1" xsi:type="array">
+                    <item name="is_default" xsi:type="string">No</item>
+                    <item name="admin" xsi:type="string">SIZE_M</item>
+                    <item name="view" xsi:type="string">SIZE_M</item>
+                </item>
+                <item name="2" xsi:type="array">
+                    <item name="is_default" xsi:type="string">No</item>
+                    <item name="admin" xsi:type="string">SIZE_L</item>
+                    <item name="view" xsi:type="string">SIZE_L</item>
+                </item>
+            </field>
+        </dataset>
+
+        <dataset name="sizes_for_promo_rules">
+            <field name="frontend_label" xsi:type="string">size_%isolation%</field>
+            <field name="attribute_code" xsi:type="string">size_%isolation%</field>
+            <field name="frontend_input" xsi:type="string">Dropdown</field>
+            <field name="is_used_for_promo_rules" xsi:type="string">Yes</field>
+            <field name="is_required" xsi:type="string">No</field>
+            <field name="options" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="is_default" xsi:type="string">Yes</item>
+                    <item name="admin" xsi:type="string">SIZE_S_%isolation%</item>
+                    <item name="view" xsi:type="string">SIZE_S</item>
+                </item>
+                <item name="1" xsi:type="array">
+                    <item name="is_default" xsi:type="string">No</item>
+                    <item name="admin" xsi:type="string">SIZE_M_%isolation%</item>
+                    <item name="view" xsi:type="string">SIZE_M</item>
+                </item>
+                <item name="2" xsi:type="array">
+                    <item name="is_default" xsi:type="string">No</item>
+                    <item name="admin" xsi:type="string">SIZE_L_%isolation%</item>
+                    <item name="view" xsi:type="string">SIZE_L</item>
+                    <item name="promo" xsi:type="string">Yes</item>
+                </item>
+            </field>
+        </dataset>
     </repository>
 </config>
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 997d0ab1d7f11c64ce33ea386870055ea2e77798..b42757b07b2d250cfc82f74e475c7ca683e1f7ee 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
@@ -68,6 +68,37 @@
             </field>
         </dataset>
 
+        <dataset name="product_with_long_name">
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="name" xsi:type="string">Product with long name %isolation%%isolation%%isolation%%isolation%%isolation%%isolation%%isolation%%isolation%%isolation%%isolation%%isolation%%isolation%%isolation%%isolation%</field>
+            <field name="sku" xsi:type="string">sku_simple_product_%isolation%</field>
+            <field name="is_virtual" xsi:type="string">No</field>
+            <field name="product_has_weight" xsi:type="string">This item has weight</field>
+            <field name="weight" xsi:type="string">1</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>
+
         <dataset name="product_with_custom_color_attribute">
             <field name="name" xsi:type="string">Simple Product %isolation%</field>
             <field name="sku" xsi:type="string">simple_product_%isolation%</field>
@@ -1307,6 +1338,39 @@
             </field>
         </dataset>
 
+        <dataset name="simple_10_dollar_buy_all">
+            <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="url_key" xsi:type="string">simple-product-%isolation%</field>
+            <field name="product_has_weight" xsi:type="string">This item has weight</field>
+            <field name="weight" xsi:type="string">1</field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="qty" xsi:type="string">1</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">10</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="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">simple_order_default</item>
+            </field>
+            <field name="category_ids" xsi:type="array">
+                <item name="dataset" xsi:type="string">default_subcategory</item>
+            </field>
+        </dataset>
+
         <dataset name="simple_with_tier_price_and_order_qty_3">
             <field name="attribute_set_id" xsi:type="array">
                 <item name="dataset" xsi:type="string">default</item>
@@ -1368,44 +1432,46 @@
             <field name="url_key" xsi:type="string">overnight-duffle</field>
         </dataset>
 
-        <dataset name="simple_with_weight_10_for_salesrule">
+        <dataset name="with_percent_and_fixed_custom_option">
             <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="price" xsi:type="array">
+                <item name="value" xsi:type="string">56.78</item>
+            </field>
             <field name="product_has_weight" xsi:type="string">This item has weight</field>
-            <field name="weight" xsi:type="string">10</field>
+            <field name="weight" xsi:type="string">1</field>
             <field name="quantity_and_stock_status" xsi:type="array">
-                <item name="qty" xsi:type="string">25</item>
+                <item name="qty" xsi:type="string">1</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="category_ids" xsi:type="array">
+                <item name="dataset" xsi:type="string">default_subcategory</item>
+            </field>
+            <field name="custom_options" xsi:type="array">
+                <item name="dataset" xsi:type="string">percent_and_fixed_radio_options</item>
+            </field>
             <field name="checkout_data" xsi:type="array">
-                <item name="dataset" xsi:type="string">simple_order_default</item>
+                <item name="dataset" xsi:type="string">with_fixed_custom_option</item>
             </field>
         </dataset>
 
-        <dataset name="with_default_custom_option">
+        <dataset name="with_fixed_custom_option_price_100">
             <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="price" xsi:type="array">
-                <item name="value" xsi:type="string">56.78</item>
+                <item name="value" xsi:type="string">100</item>
             </field>
             <field name="product_has_weight" xsi:type="string">This item has weight</field>
             <field name="weight" xsi:type="string">1</field>
@@ -1423,14 +1489,14 @@
                 <item name="dataset" xsi:type="string">default_subcategory</item>
             </field>
             <field name="custom_options" xsi:type="array">
-                <item name="dataset" xsi:type="string">percent_and_fixed_radio_options</item>
+                <item name="dataset" xsi:type="string">text_and_two_custom_options</item>
             </field>
             <field name="checkout_data" xsi:type="array">
-                <item name="dataset" xsi:type="string">simple_order_qty_1_price_56</item>
+                <item name="dataset" xsi:type="string">text_and_two_custom_options</item>
             </field>
         </dataset>
 
-        <dataset name="with_fixed_custom_option">
+        <dataset name="with_custom_options_and_price_56_78">
             <field name="attribute_set_id" xsi:type="array">
                 <item name="dataset" xsi:type="string">default</item>
             </field>
@@ -1458,11 +1524,131 @@
                 <item name="dataset" xsi:type="string">percent_and_fixed_radio_options</item>
             </field>
             <field name="checkout_data" xsi:type="array">
-                <item name="dataset" xsi:type="string">with_fixed_custom_option</item>
+                <item name="dataset" xsi:type="string">with_percent_custom_option</item>
+            </field>
+        </dataset>
+
+        <dataset name="product_with_price_20_01">
+            <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">1</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">20.01</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>
+
+        <dataset name="product_with_price_79_99">
+            <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">1</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">79.99</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>
 
-        <dataset name="with_percent_custom_option">
+        <dataset name="simple_with_weight_10">
+            <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>
+
+        <dataset name="default_with_weight_2">
+            <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">2</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>
+
+        <dataset name="with_default_custom_option">
             <field name="attribute_set_id" xsi:type="array">
                 <item name="dataset" xsi:type="string">default</item>
             </field>
@@ -1490,9 +1676,128 @@
                 <item name="dataset" xsi:type="string">percent_and_fixed_radio_options</item>
             </field>
             <field name="checkout_data" xsi:type="array">
-                <item name="dataset" xsi:type="string">with_percent_custom_option</item>
+                <item name="dataset" xsi:type="string">simple_order_qty_1_price_56</item>
+            </field>
+        </dataset>
+
+        <dataset name="default_qty_3">
+            <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">1</field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="qty" xsi:type="string">3</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>
 
+        <dataset name="default_qty_1">
+            <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">1</field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="qty" xsi:type="string">1</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>
+
+        <dataset name="default_qty_2">
+            <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">1</field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="qty" xsi:type="string">2</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>
+
+        <dataset name="default_in_custom_website">
+            <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">1</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">custom_store</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/Catalog/Test/Repository/CatalogProductSimple/CheckoutData.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple/CheckoutData.xml
index a1f34f46b0a7cb89342a17a382a0ba1c86de9059..dc570b0bf7f2780ba878bdae30fa61f22ca4133a 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple/CheckoutData.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple/CheckoutData.xml
@@ -165,6 +165,44 @@
             <field name="qty" xsi:type="string">3</field>
         </dataset>
 
+        <dataset name="with_fixed_custom_option">
+            <field name="options" xsi:type="array">
+                <item name="custom_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_0</item>
+                    </item>
+                </item>
+            </field>
+            <field name="qty" xsi:type="string">1</field>
+            <field name="cartItem" xsi:type="array">
+                <item name="price" xsi:type="string">560.78</item>
+                <item name="qty" xsi:type="string">1</item>
+                <item name="subtotal" xsi:type="string">560.78</item>
+            </field>
+        </dataset>
+
+        <dataset name="text_and_two_custom_options">
+            <field name="options" xsi:type="array">
+                <item name="custom_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">Ok</item>
+                    </item>
+                    <item name="1" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_1</item>
+                        <item name="value" xsi:type="string">option_key_0</item>
+                    </item>
+                </item>
+            </field>
+            <field name="qty" xsi:type="string">1</field>
+            <field name="cartItem" xsi:type="array">
+                <item name="price" xsi:type="string">5</item>
+                <item name="qty" xsi:type="string">1</item>
+                <item name="subtotal" xsi:type="string">125</item>
+            </field>
+        </dataset>
+
         <dataset name="simple_order_qty_1_price_56">
             <field name="qty" xsi:type="string">1</field>
             <field name="cartItem" xsi:type="array">
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.xml
index 7f56333969a0de17d607192ad5b0f77741f45626..7effa080dc6819d026deb85032c4f93ca0c1b05f 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.xml
@@ -75,6 +75,36 @@
             </field>
         </dataset>
 
+        <dataset name="virtual_low_stock">
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="status" xsi:type="string">Yes</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="url_key" xsi:type="string">virtual-product%isolation%</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="name" xsi:type="string">Virtual product %isolation%</field>
+            <field name="sku" xsi:type="string">sku_virtual_product_%isolation%</field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="qty" xsi:type="string">1</item>
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="product_has_weight" xsi:type="string">This item has no weight</field>
+            <field name="price" xsi:type="array">
+                <item name="value" xsi:type="string">10</item>
+            </field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">virtual_order_default</item>
+            </field>
+        </dataset>
+
         <dataset name="virtual_big_qty">
             <field name="tax_class_id" xsi:type="array">
                 <item name="dataset" xsi:type="string">taxable_goods</item>
@@ -188,5 +218,35 @@
                 <item name="dataset" xsi:type="string">virtual_order_default</item>
             </field>
         </dataset>
+
+        <dataset name="buy_all">
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="status" xsi:type="string">Yes</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="url_key" xsi:type="string">virtual-product%isolation%</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="name" xsi:type="string">Virtual product %isolation%</field>
+            <field name="sku" xsi:type="string">sku_virtual_product_%isolation%</field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="qty" xsi:type="string">1</item>
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="product_has_weight" xsi:type="string">This item has no weight</field>
+            <field name="price" xsi:type="array">
+                <item name="value" xsi:type="string">10</item>
+            </field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">virtual_order_default</item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Category.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Category.xml
index dc5e9c12ebcaebc1e49c8394f4d4308a11762309..82e7e8e6edeae17de48a6f62af1539464910620e 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Category.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Category.xml
@@ -73,6 +73,36 @@
             <field name="include_in_menu" xsi:type="string">Yes</field>
         </dataset>
 
+        <dataset name="three_nested_categories">
+            <field name="name" xsi:type="string">Category%isolation%</field>
+            <field name="url_key" xsi:type="string">category-%isolation%</field>
+            <field name="parent_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">two_nested_categories</item>
+            </field>
+            <field name="is_active" xsi:type="string">Yes</field>
+            <field name="include_in_menu" xsi:type="string">Yes</field>
+        </dataset>
+
+        <dataset name="four_nested_categories">
+            <field name="name" xsi:type="string">Category%isolation%</field>
+            <field name="url_key" xsi:type="string">category-%isolation%</field>
+            <field name="parent_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">three_nested_categories</item>
+            </field>
+            <field name="is_active" xsi:type="string">Yes</field>
+            <field name="include_in_menu" xsi:type="string">Yes</field>
+        </dataset>
+
+        <dataset name="five_nested_categories">
+            <field name="name" xsi:type="string">Category%isolation%</field>
+            <field name="url_key" xsi:type="string">category-%isolation%</field>
+            <field name="parent_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">four_nested_categories</item>
+            </field>
+            <field name="is_active" xsi:type="string">Yes</field>
+            <field name="include_in_menu" xsi:type="string">Yes</field>
+        </dataset>
+
         <dataset name="default_subcategory_with_assigned_simple_product">
             <field name="name" xsi:type="string">Category%isolation%</field>
             <field name="url_key" xsi:type="string">category%isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/CustomOptions.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/CustomOptions.xml
index b977e23166f45ec9c471ea08c5e7dc7516a728c0..89e1f07ee60222471e05e682bd0d44d25c90551c 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/CustomOptions.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/CustomOptions.xml
@@ -383,6 +383,98 @@
             </field>
         </dataset>
 
+        <dataset name="text_and_two_custom_options">
+            <field name="0" xsi:type="array">
+                <item name="title" xsi:type="string">30 bucks</item>
+                <item name="is_require" xsi:type="string">Yes</item>
+                <item name="type" xsi:type="string">Text/Field</item>
+                <item name="options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="price" xsi:type="string">30</item>
+                        <item name="price_type" xsi:type="string">Fixed</item>
+                        <item name="sku" xsi:type="string">sku_field_option_%isolation%</item>
+                        <item name="max_characters" xsi:type="string">1024</item>
+                    </item>
+                </item>
+            </field>
+            <field name="1" xsi:type="array">
+                <item name="title" xsi:type="string">custom menu</item>
+                <item name="is_require" xsi:type="string">Yes</item>
+                <item name="type" xsi:type="string">Select/Radio Buttons</item>
+                <item name="options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">5 bucks</item>
+                        <item name="price" xsi:type="string">5</item>
+                        <item name="price_type" xsi:type="string">Fixed</item>
+                        <item name="sku" xsi:type="string">sku_radio_buttons_row_1</item>
+                        <item name="sort_order" xsi:type="string">0</item>
+                    </item>
+                    <item name="1" xsi:type="array">
+                        <item name="title" xsi:type="string">10 bucks</item>
+                        <item name="price" xsi:type="string">10</item>
+                        <item name="price_type" xsi:type="string">Fixed</item>
+                        <item name="sku" xsi:type="string">sku_radio_buttons_row_2</item>
+                        <item name="sort_order" xsi:type="string">1</item>
+                    </item>
+                </item>
+            </field>
+        </dataset>
+
+        <dataset name="two_fixed_radio_options">
+            <field name="0" xsi:type="array">
+                <item name="title" xsi:type="string">custom menu</item>
+                <item name="is_require" xsi:type="string">No</item>
+                <item name="type" xsi:type="string">Select/Radio Buttons</item>
+                <item name="options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">12 bucks</item>
+                        <item name="price" xsi:type="string">12</item>
+                        <item name="price_type" xsi:type="string">Fixed</item>
+                        <item name="sku" xsi:type="string">sku_radio_buttons_row_1</item>
+                        <item name="sort_order" xsi:type="string">0</item>
+                    </item>
+                    <item name="1" xsi:type="array">
+                        <item name="title" xsi:type="string">89 bucks</item>
+                        <item name="price" xsi:type="string">89</item>
+                        <item name="price_type" xsi:type="string">Fixed</item>
+                        <item name="sku" xsi:type="string">sku_radio_buttons_row_2</item>
+                        <item name="sort_order" xsi:type="string">0</item>
+                    </item>
+                </item>
+            </field>
+        </dataset>
+
+        <dataset name="drop_down_with_three_options">
+            <field name="0" xsi:type="array">
+                <item name="title" xsi:type="string">custom option drop down %isolation%</item>
+                <item name="is_require" xsi:type="string">Yes</item>
+                <item name="type" xsi:type="string">Select/Drop-down</item>
+                <item name="options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">12 bucks</item>
+                        <item name="price" xsi:type="string">12</item>
+                        <item name="price_type" xsi:type="string">Fixed</item>
+                        <item name="sku" xsi:type="string">sku_radio_buttons_row_1</item>
+                        <item name="sort_order" xsi:type="string">0</item>
+                    </item>
+                    <item name="1" xsi:type="array">
+                        <item name="title" xsi:type="string">12 bucks</item>
+                        <item name="price" xsi:type="string">12</item>
+                        <item name="price_type" xsi:type="string">Fixed</item>
+                        <item name="sku" xsi:type="string">sku_radio_buttons_row_1</item>
+                        <item name="sort_order" xsi:type="string">0</item>
+                    </item>
+                    <item name="2" xsi:type="array">
+                        <item name="title" xsi:type="string">12 bucks</item>
+                        <item name="price" xsi:type="string">12</item>
+                        <item name="price_type" xsi:type="string">Fixed</item>
+                        <item name="sku" xsi:type="string">sku_radio_buttons_row_1</item>
+                        <item name="sort_order" xsi:type="string">0</item>
+                    </item>
+                </item>
+            </field>
+        </dataset>
+
         <dataset name="not_required_text_option">
             <field name="0" xsi:type="array">
                 <item name="title" xsi:type="string">Test1 option %isolation%</item>
@@ -398,6 +490,5 @@
                 </item>
             </field>
         </dataset>
-
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.php
index d458ffeb22475b78d66eeb6441d1f911c12b0cc8..61b0a51df65368230266644a686f4dc10e707ab1 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.php
@@ -23,7 +23,7 @@ use Magento\Mtf\TestCase\Injectable;
  * 6. Verify created category
  *
  * @group Category_Management
- * @ZephyrId MAGETWO-23411
+ * @ZephyrId MAGETWO-23411, MAGETWO-48379
  */
 class CreateCategoryEntityTest extends Injectable
 {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml
index 238fddba3de426f683e981c0a1b7b1b60c12fbeb..90863eb208ce252496e2ac002df04da6b2ee022e 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml
@@ -87,6 +87,7 @@
             <data name="category/data/schedule_update_from" xsi:type="string">01/10/2014</data>
             <data name="category/data/schedule_update_to" xsi:type="string">12/31/2024</data>
             <data name="filterByPath" xsi:type="string">request_path</data>
+            <data name="redirectType" xsi:type="string">No</data>
             <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySaveMessage" />
             <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteCategoryInGrid" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForm" />
@@ -153,11 +154,10 @@
             <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySaveMessage" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForAssignedProducts" />
         </variation>
-        <variation name="CreateCategoryEntityTestVariation9_ThreeNesting">
+        <variation name="CreateCategoryEntityTestVariation9_FiveNesting" summary="Create category with five nesting" ticketId="MAGETWO-48379">
             <data name="tag" xsi:type="string">test_type:extended_acceptance_test</data>
-            <data name="description" xsi:type="string">Create category with three nesting</data>
             <data name="addCategory" xsi:type="string">addSubcategory</data>
-            <data name="category/data/parent_id/dataset" xsi:type="string">two_nested_categories</data>
+            <data name="category/data/parent_id/dataset" xsi:type="string">five_nested_categories</data>
             <data name="category/data/is_active" xsi:type="string">Yes</data>
             <data name="category/data/name" xsi:type="string">Category%isolation%</data>
             <data name="category/data/description" xsi:type="string">Category Required</data>
@@ -166,5 +166,14 @@
             <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySaveMessage" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryBreadcrumbs" />
         </variation>
+        <variation name="CreateCategoryEntityTestVariation10_InCustomRootCategory" summary="Create category in the custom root category that is used for custom website" ticketId="MAGETWO-12938">
+            <data name="addCategory" xsi:type="string">addSubcategory</data>
+            <data name="category/data/parent_id/dataset" xsi:type="string">root_category</data>
+            <data name="category/data/is_active" xsi:type="string">Yes</data>
+            <data name="category/data/include_in_menu" xsi:type="string">Yes</data>
+            <data name="category/data/name" xsi:type="string">Subcategory%isolation%</data>
+            <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySaveMessage" />
+            <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryOnCustomWebsite" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/MoveCategoryEntityTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/MoveCategoryEntityTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..cebcd14ab050f7ee4121cc33199c29f4d58327f8
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/MoveCategoryEntityTest.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\TestCase\Category;
+
+use Magento\Catalog\Test\Fixture\Category;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogCategoryEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogCategoryIndex;
+use Magento\Mtf\TestCase\Injectable;
+
+/**
+ * Precondition:
+ * 1. Categories are created
+ *
+ * Test Flow:
+ * 1. Log in to Backend
+ * 2. Navigate to the Products>Inventory>Categories
+ * 3. Click on 'Add Category' button
+ * 4. Fill out all data according to data set
+ * 5. Save category
+ * 6. Verify created category
+ *
+ * @group Category_Management
+ * @ZephyrId MAGETWO-27319
+ */
+class MoveCategoryEntityTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    /* end tags */
+
+    /**
+     * CatalogCategoryIndex page.
+     *
+     * @var CatalogCategoryIndex
+     */
+    private $catalogCategoryIndex;
+
+    /**
+     * CatalogCategoryEdit page.
+     *
+     * @var CatalogCategoryEdit
+     */
+    private $catalogCategoryEdit;
+
+    /**
+     * Inject page end prepare default category.
+     *
+     * @param CatalogCategoryIndex $catalogCategoryIndex
+     * @param CatalogCategoryEdit $catalogCategoryEdit
+     * @return void
+     */
+    public function __inject(
+        CatalogCategoryIndex $catalogCategoryIndex,
+        CatalogCategoryEdit $catalogCategoryEdit
+    ) {
+        $this->catalogCategoryIndex = $catalogCategoryIndex;
+        $this->catalogCategoryEdit = $catalogCategoryEdit;
+    }
+
+    /**
+     * Runs test.
+     *
+     * @param Category $childCategory
+     * @param Category $parentCategory
+     * @return array
+     */
+    public function test(Category $childCategory, Category $parentCategory)
+    {
+        // Preconditions:
+        $parentCategory->persist();
+        $childCategory->persist();
+
+        // Steps:
+        $this->catalogCategoryIndex->open();
+        $this->catalogCategoryIndex->getTreeCategories()->expandAllCategories();
+        $this->catalogCategoryIndex->getTreeCategories()->assignCategory(
+            $parentCategory->getName(),
+            $childCategory->getName()
+        );
+        $this->catalogCategoryEdit->getModalBlock()->acceptWarning();
+
+        return [
+            'category' => $childCategory,
+            'parentCategory' => $parentCategory,
+            'childCategory' => $childCategory
+        ];
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/MoveCategoryEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/MoveCategoryEntityTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b3a17778970243129ed41996edeeb5d4a81cfef0
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/MoveCategoryEntityTest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\Catalog\Test\TestCase\Category\MoveCategoryEntityTest" summary="Move category from one to another" ticketId="MAGETWO-27319">
+        <variation name="MoveCategoryEntityTestVariation1">
+            <data name="childCategory/dataset" xsi:type="string">three_nested_categories</data>
+            <data name="parentCategory/dataset" xsi:type="string">default</data>
+            <data name="nestingLevel" xsi:type="string">3</data>
+            <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryMovedMessage" />
+            <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteCategoryInGrid" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/UpdateCategoryEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/UpdateCategoryEntityTest.xml
index e98cd1529409aa05e899d5bdd847783c78e16828..5b7ef1e4c341fbcde2c9dae99fb610ca2fc3c8fe 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/UpdateCategoryEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/UpdateCategoryEntityTest.xml
@@ -14,6 +14,7 @@
             <data name="category/data/description" xsi:type="string">Category Description Updated</data>
             <data name="category/data/url_key" xsi:type="string">UrlKey%isolation%</data>
             <data name="category/data/meta_title" xsi:type="string">Category Title Updated</data>
+            <data name="redirectType" xsi:type="string">No</data>
             <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySaveMessage" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForm" />
             <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteCategoryInGrid" />
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml
index 7979faa5e1f761844fa5d1bb8bebd00430e87623..d906713ae726dd1d5bb1399ec674cd054552c711 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml
@@ -542,5 +542,16 @@
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductHasImageInGrid" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertCanSaveProduct" />
         </variation>
+        <variation name="CreateSimpleProductNotVisibleIndividually" summary="Check that url rewrite is not generated for product if visibility is 'Not Visible Individually'" ticketId="MAGETWO-53788">
+            <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data>
+            <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data>
+            <data name="product/data/sku" xsi:type="string">simple_sku_%isolation%</data>
+            <data name="product/data/price/value" xsi:type="string">15</data>
+            <data name="product/data/weight" xsi:type="string">5</data>
+            <data name="product/data/quantity_and_stock_status/qty" xsi:type="string">1</data>
+            <data name="product/data/visibility" xsi:type="string">Not Visible Individually</data>
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" />
+            <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteProductNotInGrid" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/ManageProductsStockTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/ManageProductsStockTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..48553a934c8e9df9189a99205e32c094b9da4a1b
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/ManageProductsStockTest.php
@@ -0,0 +1,101 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\TestCase\Product;
+
+use Magento\Catalog\Test\Fixture\CatalogProductSimple;
+use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Mtf\TestCase\Injectable;
+
+/**
+ * Preconditions:
+ * 1. Set Configuration
+ * 2. Create products according to dataset
+ *
+ * Steps:
+ * 1. Open product on frontend
+ * 2. Add product to cart if needed
+ * 3. Perform all assertions
+ *
+ * @group Inventory
+ * @ZephyrId MAGETWO-29543, MAGETWO-13645
+ */
+class ManageProductsStockTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    /* end tags */
+
+    /**
+     * Fixture factory.
+     *
+     * @var FixtureFactory
+     */
+    protected $fixtureFactory;
+
+    /**
+     * Configuration data.
+     *
+     * @var string
+     */
+    protected $configData;
+
+    /**
+     * Setup configuration.
+     *
+     * @param FixtureFactory $fixtureFactory
+     * @return void
+     */
+    public function __inject(FixtureFactory $fixtureFactory)
+    {
+        $this->fixtureFactory = $fixtureFactory;
+    }
+
+    /**
+     * Manage products stock.
+     *
+     * @param CatalogProductSimple $product
+     * @param string $skipAddingToCart
+     * @param string $configData
+     * @return mixed
+     */
+    public function test(CatalogProductSimple $product, $skipAddingToCart = null, $configData = null)
+    {
+        $this->configData = $configData;
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData]
+        )->run();
+
+        // Preconditions
+        $product->persist();
+
+        // Steps
+        if (!$skipAddingToCart) {
+            $this->objectManager->create(
+                \Magento\Checkout\Test\TestStep\AddProductsToTheCartStep::class,
+                ['products' => [$product]]
+            )->run();
+
+            $cart['data']['items'] = ['products' => [$product]];
+
+            return ['cart' => $this->fixtureFactory->createByCode('cart', $cart)];
+        }
+    }
+
+    /**
+     * Set default configuration.
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData, 'rollback' => true]
+        )->run();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/ManageProductsStockTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/ManageProductsStockTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bf104b72fd6475cd4ea78165cb71f3c85665a4f3
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/ManageProductsStockTest.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\Catalog\Test\TestCase\Product\ManageProductsStockTest" summary="Managing products stock with several conditions" ticketId="MAGETWO-29543">
+        <variation name="ManageProductsStockTestVariation1" summary="Adding Out of Stock product to cart">
+            <data name="product/dataset" xsi:type="string">default</data>
+            <data name="product/data/qty_and_stock_status/is_in_stock" xsi:type="string">Out of Stock</data>
+            <data name="configData" xsi:type="string">display_out_of_stock,backorders_allow_qty_below</data>
+            <constraint name="Magento\Checkout\Test\Constraint\AssertAddedProductToCartSuccessMessage" />
+            <constraint name="Magento\Checkout\Test\Constraint\AssertProductQtyInShoppingCart" />
+        </variation>
+        <variation name="ManageProductsStockTestVariation2" summary="Checking that Out of Stock products are not visible in category" ticketId="MAGETWO-13645">
+            <data name="product/dataset" xsi:type="string">product_with_category</data>
+            <data name="product/data/stock_data/manage_stock" xsi:type="string">Yes</data>
+            <data name="product/data/quantity_and_stock_status/qty" xsi:type="string">5</data>
+            <data name="product/data/stock_data/use_config_min_sale_qty" xsi:type="string">Yes</data>
+            <data name="product/data/stock_data/min_sale_qty" xsi:type="string">1</data>
+            <data name="product/data/stock_data/use_config_max_sale_qty" xsi:type="string">Yes</data>
+            <data name="product/data/stock_data/max_sale_qty" xsi:type="string">10000</data>
+            <data name="product/data/stock_data/is_qty_decimal" xsi:type="string">Yes</data>
+            <data name="product/data/stock_data/enable_qty_increments" xsi:type="string">No</data>
+            <data name="product/data/stock_data/use_config_notify_stock_qty" xsi:type="string">Yes</data>
+            <data name="product/data/stock_data/notify_stock_qty" xsi:type="string">1</data>
+            <data name="product/data/stock_data/use_config_backorders" xsi:type="string">No</data>
+            <data name="product/data/quantity_and_stock_status/is_in_stock" xsi:type="string">Out of Stock</data>
+            <data name="skipAddingToCart" xsi:type="string">Yes</data>
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductNotVisibleInCategory" />
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductOutOfStock" />
+        </variation>
+        <variation name="ManageProductsStockTestVariation3" summary="Add In Stock product to cart" ticketId="MAGETWO-13645">
+            <data name="product/dataset" xsi:type="string">product_with_category</data>
+            <data name="product/data/stock_data/manage_stock" xsi:type="string">Yes</data>
+            <data name="product/data/quantity_and_stock_status/qty" xsi:type="string">5</data>
+            <data name="product/data/quantity_and_stock_status/is_in_stock" xsi:type="string">In Stock</data>
+            <data name="product/data/stock_data/use_config_min_sale_qty" xsi:type="string">Yes</data>
+            <data name="product/data/stock_data/min_sale_qty" xsi:type="string">1</data>
+            <data name="product/data/stock_data/use_config_max_sale_qty" xsi:type="string">Yes</data>
+            <data name="product/data/stock_data/max_sale_qty" xsi:type="string">10000</data>
+            <data name="product/data/stock_data/is_qty_decimal" xsi:type="string">Yes</data>
+            <data name="product/data/stock_data/enable_qty_increments" xsi:type="string">No</data>
+            <data name="product/data/stock_data/use_config_notify_stock_qty" xsi:type="string">Yes</data>
+            <data name="product/data/stock_data/notify_stock_qty" xsi:type="string">1</data>
+            <data name="product/data/stock_data/use_config_backorders" xsi:type="string">No</data>
+            <data name="skipAddingToCart" xsi:type="string">Yes</data>
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductVisibleInCategory" />
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductPage" />
+        </variation>
+        <variation name="ManageProductsStockTestVariation4" summary="Enable displaying of out of stock products in category" ticketId="MAGETWO-13645">
+            <data name="product/dataset" xsi:type="string">product_with_category</data>
+            <data name="product/data/stock_data/manage_stock" xsi:type="string">Yes</data>
+            <data name="product/data/quantity_and_stock_status/qty" xsi:type="string">5</data>
+            <data name="product/data/quantity_and_stock_status/is_in_stock" xsi:type="string">In Stock</data>
+            <data name="product/data/stock_data/use_config_min_sale_qty" xsi:type="string">Yes</data>
+            <data name="product/data/stock_data/min_sale_qty" xsi:type="string">1</data>
+            <data name="product/data/stock_data/use_config_max_sale_qty" xsi:type="string">Yes</data>
+            <data name="product/data/stock_data/max_sale_qty" xsi:type="string">10000</data>
+            <data name="product/data/stock_data/is_qty_decimal" xsi:type="string">Yes</data>
+            <data name="product/data/stock_data/enable_qty_increments" xsi:type="string">No</data>
+            <data name="product/data/stock_data/use_config_notify_stock_qty" xsi:type="string">Yes</data>
+            <data name="product/data/stock_data/notify_stock_qty" xsi:type="string">1</data>
+            <data name="product/data/stock_data/use_config_backorders" xsi:type="string">No</data>
+            <data name="skipAddingToCart" xsi:type="string">Yes</data>
+            <data name="configData" xsi:type="string">display_out_of_stock</data>
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductVisibleInCategory" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.php
index f68ec539c62e0c7b59f9c6f958bff7dc350a91d6..76d13013917ab6c322aa972fc4d190012068470b 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.php
@@ -7,10 +7,12 @@
 namespace Magento\Catalog\Test\TestCase\Product;
 
 use Magento\Catalog\Test\Fixture\CatalogProductSimple;
+use Magento\Store\Test\Fixture\Store;
 use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
 use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
-use Magento\Mtf\ObjectManager;
 use Magento\Mtf\TestCase\Injectable;
+use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Catalog\Test\Fixture\Category;
 
 /**
  * Precondition:
@@ -56,19 +58,29 @@ class UpdateSimpleProductEntityTest extends Injectable
      */
     protected $configData;
 
+    /**
+     * Fixture Factory.
+     *
+     * @var FixtureFactory
+     */
+    private $fixtureFactory;
+
     /**
      * Injection data.
      *
      * @param CatalogProductIndex $productGrid
      * @param CatalogProductEdit $editProductPage
+     * @param FixtureFactory $fixtureFactory
      * @return void
      */
     public function __inject(
         CatalogProductIndex $productGrid,
-        CatalogProductEdit $editProductPage
+        CatalogProductEdit $editProductPage,
+        FixtureFactory $fixtureFactory
     ) {
         $this->productGrid = $productGrid;
         $this->editProductPage = $editProductPage;
+        $this->fixtureFactory = $fixtureFactory;
     }
 
     /**
@@ -76,20 +88,25 @@ class UpdateSimpleProductEntityTest extends Injectable
      *
      * @param CatalogProductSimple $initialProduct
      * @param CatalogProductSimple $product
+     * @param Store|null $store
      * @param string $configData
      * @return array
      */
-    public function test(CatalogProductSimple $initialProduct, CatalogProductSimple $product, $configData = '')
-    {
+    public function test(
+        CatalogProductSimple $initialProduct,
+        CatalogProductSimple $product,
+        Store $store = null,
+        $configData = ''
+    ) {
         $this->configData = $configData;
         // Preconditions
         $initialProduct->persist();
-        $initialCategory = $initialProduct->hasData('category_ids')
-            ? $initialProduct->getDataFieldConfig('category_ids')['source']->getCategories()[0]
-            : null;
-        $category = $product->hasData('category_ids') && $product->getCategoryIds()[0]
-            ? $product->getDataFieldConfig('category_ids')['source']->getCategories()[0]
-            : $initialCategory;
+        $category = $this->getCategory($initialProduct, $product);
+
+        if ($store) {
+            $store->persist();
+            $productName[$store->getStoreId()] = $product->getName();
+        }
 
         $this->objectManager->create(
             \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
@@ -101,10 +118,34 @@ class UpdateSimpleProductEntityTest extends Injectable
 
         $this->productGrid->open();
         $this->productGrid->getProductGrid()->searchAndOpen($filter);
+        if ($store) {
+            $this->editProductPage->getFormPageActions()->changeStoreViewScope($store);
+        }
         $this->editProductPage->getProductForm()->fill($product);
         $this->editProductPage->getFormPageActions()->save();
 
-        return ['category' => $category];
+        return [
+            'category' => $category,
+            'stores' => isset($store) ? [$store] : [],
+            'productNames' => isset($productName) ? $productName : [],
+        ];
+    }
+
+    /**
+     * Get Category instance.
+     *
+     * @param CatalogProductSimple $initialProduct
+     * @param CatalogProductSimple $product
+     * @return Category
+     */
+    protected function getCategory(CatalogProductSimple $initialProduct, CatalogProductSimple $product)
+    {
+        $initialCategory = $initialProduct->hasData('category_ids')
+            ? $initialProduct->getDataFieldConfig('category_ids')['source']->getCategories()[0]
+            : null;
+        return $product->hasData('category_ids') && $product->getCategoryIds()[0]
+            ? $product->getDataFieldConfig('category_ids')['source']->getCategories()[0]
+            : $initialCategory;
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.xml
index 31aaad654f92a914c14276ab770fa7fe9790f5de..b211242bbd0b04ba376e0f4414c8274beba9209c 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.xml
@@ -169,5 +169,13 @@
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductForm" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductInCart" />
         </variation>
+        <variation name="UpdateSimpleProductEntityTestVariation12" summary="Verify data overriding on Store View level" ticketId="MAGETWO-50640">
+            <data name="initialProduct/dataset" xsi:type="string">product_with_category</data>
+            <data name="store/dataset" xsi:type="string">custom</data>
+            <data name="product/data/use_default_name" xsi:type="string">No</data>
+            <data name="product/data/name" xsi:type="string">Test simple product %isolation%</data>
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" />
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductNameOnDifferentStoreViews" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml
index 543bece9331f4d0968e38b7d8f887f563b9b8ec3..1726ffb7f9828ce9810fe4c3f3d77c8a585649d0 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml
@@ -19,8 +19,7 @@
             <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeForm" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" />
         </variation>
-        <variation name="CreateProductAttributeEntityTestVariation2">
-            <data name="tag" xsi:type="string">to_maintain:yes</data>
+        <variation name="CreateProductAttributeEntityTestVariation2"  summary="Create custom text attribute product field" ticketId="MAGETWO-17475">
             <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data>
             <data name="productAttribute/data/frontend_label" xsi:type="string">Text_Field_Admin_%isolation%</data>
             <data name="productAttribute/data/frontend_input" xsi:type="string">Text Area</data>
@@ -37,6 +36,7 @@
             <data name="sectionName" xsi:type="string">product-details</data>
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeInGrid" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeForm" />
+            <constraint name="Magento\CatalogSearch\Test\Constraint\AssertAdvancedSearchProductByAttribute" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsRequired" />
             <constraint name="Magento\CatalogSearch\Test\Constraint\AssertAttributeSearchableByLabel" />
@@ -114,8 +114,8 @@
             <constraint name="Magento\CatalogSearch\Test\Constraint\AssertAttributeSearchableByLabel" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeOptionsOnProductForm" />
         </variation>
-        <variation name="CreateProductAttributeEntityTestVariation6">
-            <data name="tag" xsi:type="string">test_type:extended_acceptance_test, to_maintain:yes</data>
+        <variation name="CreateProductAttributeEntityTestVariation6" summary="Create custom dropdown attribute product field" ticketId="MAGETWO-17475">
+            <data name="tag" xsi:type="string">test_type:extended_acceptance_test</data>
             <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data>
             <data name="productAttribute/data/frontend_label" xsi:type="string">Dropdown_Admin_%isolation%</data>
             <data name="productAttribute/data/frontend_input" xsi:type="string">Dropdown</data>
@@ -139,6 +139,7 @@
             <data name="sectionName" xsi:type="string">product-details</data>
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeInGrid" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeForm" />
+            <constraint name="Magento\CatalogSearch\Test\Constraint\AssertAdvancedSearchProductByAttribute" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsRequired" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsGlobal" />
@@ -152,8 +153,7 @@
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsFilterableInSearch" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeOptionsOnProductForm" />
         </variation>
-        <variation name="CreateProductAttributeEntityTestVariation7">
-            <data name="tag" xsi:type="string">to_maintain:yes</data>
+        <variation name="CreateProductAttributeEntityTestVariation7" summary="Create custom price attribute product field" ticketId="MAGETWO-17475">
             <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data>
             <data name="productAttribute/data/frontend_label" xsi:type="string">Price_Admin_%isolation%</data>
             <data name="productAttribute/data/frontend_input" xsi:type="string">Price</data>
@@ -169,6 +169,7 @@
             <data name="attributeValue" xsi:type="number">15</data>
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeInGrid" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeForm" />
+            <constraint name="Magento\CatalogSearch\Test\Constraint\AssertAdvancedSearchProductByAttribute" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeDisplayingOnSearchForm" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsFilterable" />
diff --git a/dev/tests/functional/tests/app/Magento/CatalogInventory/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/CatalogInventory/Test/Repository/ConfigData.xml
index 8e5888431b3b256a80c8996526f9d605fcb97ec2..4798bdebbee4e99998dac2d0efdea7846fae03b0 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogInventory/Test/Repository/ConfigData.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogInventory/Test/Repository/ConfigData.xml
@@ -25,6 +25,15 @@
             </field>
         </dataset>
 
+        <dataset name="decrease_stock_after_order_no">
+            <field name="cataloginventory/options/can_subtract" xsi:type="array">
+                <item name="scope" xsi:type="string">cataloginventory</item>
+                <item name="scope_id" xsi:type="number">1</item>
+                <item name="label" xsi:type="string">No</item>
+                <item name="value" xsi:type="number">0</item>
+            </field>
+        </dataset>
+
         <dataset name="display_out_of_stock_rollback">
             <field name="cataloginventory/options/show_out_of_stock" xsi:type="array">
                 <item name="scope" xsi:type="string">cataloginventory</item>
@@ -42,5 +51,14 @@
                 <item name="value" xsi:type="number">0</item>
             </field>
         </dataset>
+
+        <dataset name="decrease_stock_after_order_no_rollback">
+            <field name="cataloginventory/options/can_subtract" xsi:type="array">
+                <item name="scope" xsi:type="string">cataloginventory</item>
+                <item name="scope_id" xsi:type="number">1</item>
+                <item name="label" xsi:type="string">Yes</item>
+                <item name="value" xsi:type="number">1</item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleAppliedCatalogPage.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleAppliedCatalogPage.php
index 1a83f4258a4ceb025e92bd1c7b92839c34c31b58..73b09e78cbdf2cbd5b9235f8332af3de6453ea70 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleAppliedCatalogPage.php
+++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleAppliedCatalogPage.php
@@ -53,9 +53,11 @@ class AssertCatalogPriceRuleAppliedCatalogPage extends AbstractConstraint
                 $priceBlock->isVisible(),
                 'Price block is not displayed for product ' . $product->getName()
             );
-            $actualPrice['regular'] = (float)$priceBlock->getOldPrice();
             $actualPrice['special'] = (float)$priceBlock->getSpecialPrice();
-            $actualPrice['discount_amount'] = $actualPrice['regular'] - $actualPrice['special'];
+            if ($productPrice[$key]['regular'] !== 'No') {
+                $actualPrice['regular'] = (float)$priceBlock->getOldPrice();
+                $actualPrice['discount_amount'] = $actualPrice['regular'] - $actualPrice['special'];
+            }
             $diff = $this->verifyData($actualPrice, $productPrice[$key]);
             \PHPUnit_Framework_Assert::assertTrue(
                 empty($diff),
diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleAppliedProductPage.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleAppliedProductPage.php
index 653792417be5adf969dcb89931a1f1722a359aff..be71e19d0e52e1626fab5987102686f528d8ca1b 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleAppliedProductPage.php
+++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleAppliedProductPage.php
@@ -53,9 +53,11 @@ class AssertCatalogPriceRuleAppliedProductPage extends AbstractConstraint
 
             $catalogProductViewPage->getViewBlock()->waitLoader();
             $productPriceBlock = $catalogProductViewPage->getViewBlock()->getPriceBlock();
-            $actualPrice['regular'] = $productPriceBlock->getOldPrice();
             $actualPrice['special'] = $productPriceBlock->getSpecialPrice();
-            $actualPrice['discount_amount'] = $actualPrice['regular'] - $actualPrice['special'];
+            if ($productPrice[$key]['regular'] !== 'No') {
+                $actualPrice['regular'] = $productPriceBlock->getOldPrice();
+                $actualPrice['discount_amount'] = $actualPrice['regular'] - $actualPrice['special'];
+            }
             $diff = $this->verifyData($actualPrice, $productPrice[$key]);
             \PHPUnit_Framework_Assert::assertTrue(
                 empty($diff),
diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleAppliedOnepageCheckout.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleOnOnepageCheckout.php
similarity index 97%
rename from dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleAppliedOnepageCheckout.php
rename to dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleOnOnepageCheckout.php
index 04b1f3a7093e0778fcaed39188b6f55c51858c36..57b403adcc37befe723d4e1ed9ac929c4052a2fe 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleAppliedOnepageCheckout.php
+++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleOnOnepageCheckout.php
@@ -13,7 +13,7 @@ use Magento\Mtf\Constraint\AbstractConstraint;
 /**
  * Assert that Catalog Price Rule is applied on OnePage Checkout page.
  */
-class AssertCatalogPriceRuleAppliedOnepageCheckout extends AbstractConstraint
+class AssertCatalogPriceRuleOnOnepageCheckout extends AbstractConstraint
 {
     /* tags */
     const SEVERITY = 'high';
diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplyCatalogPriceRulesTest.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplyCatalogPriceRulesTest.php
index 68972e5bb766d458425ad6bf0796760325b931e8..79783c06cfb293ac21e45a9f25717703b809a118 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplyCatalogPriceRulesTest.php
+++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplyCatalogPriceRulesTest.php
@@ -35,6 +35,13 @@ class ApplyCatalogPriceRulesTest extends AbstractCatalogRuleEntityTest
     const MVP = 'yes';
     /* end tags */
 
+    /**
+     * Index number of promo product.
+     *
+     * @var int
+     */
+    protected $promo;
+
     /**
      * Apply catalog price rules.
      *
@@ -45,6 +52,7 @@ class ApplyCatalogPriceRulesTest extends AbstractCatalogRuleEntityTest
      * @param bool $isCronEnabled
      * @param Customer $customer
      * @param array $products
+     * @param int $promo
      * @return FixtureInterface[]
      */
     public function test(
@@ -54,8 +62,10 @@ class ApplyCatalogPriceRulesTest extends AbstractCatalogRuleEntityTest
         Cron $cron,
         $isCronEnabled = false,
         Customer $customer = null,
-        array $products = null
+        array $products = [],
+        $promo = 0
     ) {
+        $this->promo = $promo;
         if ($customer !== null) {
             $customer->persist();
         }
@@ -87,29 +97,47 @@ class ApplyCatalogPriceRulesTest extends AbstractCatalogRuleEntityTest
      * @param array $catalogPriceRule
      * @return array
      */
-    private function prepareCondition(FixtureInterface $product, array $catalogPriceRule)
+    protected function prepareCondition(FixtureInterface $product, array $catalogPriceRule)
     {
-        $result = [];
         $conditionEntity = explode('|', trim($catalogPriceRule['data']['rule'], '[]'))[0];
-
-        switch ($conditionEntity) {
-            case 'Category':
-                $result['%category_id%'] = $product->getDataFieldConfig('category_ids')['source']->getIds()[0];
-                break;
-            case 'Attribute':
-                /** @var \Magento\Catalog\Test\Fixture\CatalogProductAttribute[] $attrs */
-                $attributes = $product->getDataFieldConfig('attribute_set_id')['source']
-                    ->getAttributeSet()->getDataFieldConfig('assigned_attributes')['source']->getAttributes();
-
-                $result['%attribute_id%'] = $attributes[0]->getAttributeCode();
-                $result['%attribute_value%'] = $attributes[0]->getOptions()[0]['id'];
-                break;
-        }
-        foreach ($result as $key => $value) {
-            $catalogPriceRule['data']['rule'] = str_replace($key, $value, $catalogPriceRule['data']['rule']);
+        $actionName = 'get' . $conditionEntity;
+        if (method_exists($this, $actionName)) {
+            $result = $this->$actionName($product);
+            foreach ($result as $key => $value) {
+                $catalogPriceRule['data']['rule'] = str_replace($key, $value, $catalogPriceRule['data']['rule']);
+            }
+            return $catalogPriceRule;
+        } else {
+            $message = sprintf('Method "%s" does not exist in %s', $actionName, get_class($this));
+            throw new \BadMethodCallException($message);
         }
+    }
 
-        return $catalogPriceRule;
+    /**
+     * Add category_id to catalog price rule.
+     *
+     * @param FixtureInterface $product
+     * @return array
+     */
+    protected function getCategory(FixtureInterface $product)
+    {
+        $result['%category_id%'] = $product->getDataFieldConfig('category_ids')['source']->getIds()[0];
+        return $result;
+    }
+
+    /**
+     * Add attribute_id to catalog price rule.
+     *
+     * @param FixtureInterface $product
+     * @return array
+     */
+    protected function getAttribute(FixtureInterface $product)
+    {
+        $attributes = $product->getDataFieldConfig('attribute_set_id')['source']
+            ->getAttributeSet()->getDataFieldConfig('assigned_attributes')['source']->getAttributes();
+        $result['%attribute_id%'] = $attributes[0]->getAttributeCode();
+        $result['%attribute_value%'] = $attributes[0]->getOptions()[$this->promo]['id'];
+        return $result;
     }
 
     /**
@@ -119,7 +147,7 @@ class ApplyCatalogPriceRulesTest extends AbstractCatalogRuleEntityTest
      * @param Customer $customer
      * @return array
      */
-    private function applyCustomerGroup(array $catalogPriceRule, Customer $customer)
+    protected function applyCustomerGroup(array $catalogPriceRule, Customer $customer)
     {
         /** @var \Magento\Customer\Test\Fixture\CustomerGroup $customerGroup */
         $customerGroup = $customer->getDataFieldConfig('group_id')['source']->getCustomerGroup();
@@ -136,7 +164,7 @@ class ApplyCatalogPriceRulesTest extends AbstractCatalogRuleEntityTest
      * @param Customer $customer
      * @return CatalogRule
      */
-    private function createCatalogPriceRule(
+    protected function createCatalogPriceRule(
         array $catalogPriceRule,
         FixtureInterface $product,
         Customer $customer = null
diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplyCatalogPriceRulesTest.xml b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplyCatalogPriceRulesTest.xml
index 00b02c61bd61cb07587fd2df00ef035d85c09b95..a24c571a9b829591352adf8b397c94d818d239c7 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplyCatalogPriceRulesTest.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/ApplyCatalogPriceRulesTest.xml
@@ -115,8 +115,8 @@
         </variation>
         <variation name="ApplyCatalogRuleForSimpleProductWithCustomOptions" summary="Apply Catalog Rule for Simple Product With Custom Options" ticketId="MAGETWO-23038">
             <data name="products/0" xsi:type="string">catalogProductSimple::with_default_custom_option</data>
-            <data name="products/1" xsi:type="string">catalogProductSimple::with_fixed_custom_option</data>
-            <data name="products/2" xsi:type="string">catalogProductSimple::with_percent_custom_option</data>
+            <data name="products/1" xsi:type="string">catalogProductSimple::with_percent_and_fixed_custom_option</data>
+            <data name="products/2" xsi:type="string">catalogProductSimple::with_custom_options_and_price_56_78</data>
             <data name="customer/dataset" xsi:type="string">customer_US</data>
             <data name="catalogRules/0/data/name" xsi:type="string">CatalogPriceRule %isolation%</data>
             <data name="catalogRules/0/data/is_active" xsi:type="string">Active</data>
@@ -144,7 +144,56 @@
             <data name="shippingAddress/dataset" xsi:type="string">UK_address</data>
             <data name="payment/method" xsi:type="string">free</data>
             <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedShoppingCart" />
-            <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedOnepageCheckout" />
+            <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleOnOnepageCheckout" />
+        </variation>
+        <variation name="ApplyCatalogRuleForSimpleProductAndConfigurableProduct" summary="Apply Catalog Rule For Simple Product And Configurable Product" ticketId="MAGETWO-20616">
+            <data name="products/0" xsi:type="string">configurableProduct::product_with_price_10</data>
+            <data name="products/1" xsi:type="string">catalogProductSimple::simple_10_dollar</data>
+            <data name="catalogRules/0/data/customer_group_ids/option_0" xsi:type="string">NOT LOGGED IN</data>
+            <data name="catalogRules/0/data/name" xsi:type="string">CatalogPriceRule %isolation%</data>
+            <data name="catalogRules/0/data/stop_rules_processing" xsi:type="string">Yes</data>
+            <data name="catalogRules/0/data/is_active" xsi:type="string">Active</data>
+            <data name="catalogRules/0/data/website_ids/option_0" xsi:type="string">Main Website</data>
+            <data name="catalogRules/0/data/simple_action" xsi:type="string">Apply as percentage of original</data>
+            <data name="catalogRules/0/data/discount_amount" xsi:type="string">10</data>
+            <data name="cartPrice/sub_total" xsi:type="string">18</data>
+            <data name="cartPrice/grand_total" xsi:type="string">28</data>
+            <data name="productPrice/0/special" xsi:type="string">9</data>
+            <data name="productPrice/0/sub_total" xsi:type="string">9</data>
+            <data name="productPrice/0/regular" xsi:type="string">No</data>
+            <data name="productPrice/1/special" xsi:type="string">9</data>
+            <data name="productPrice/1/sub_total" xsi:type="string">9</data>
+            <data name="productPrice/1/regular" xsi:type="string">10</data>
+            <data name="productPrice/1/discount_amount" xsi:type="string">1</data>
+            <data name="customer/dataset" xsi:type="string">customer_US</data>
+            <data name="customer/data/group_id/dataset" xsi:type="string">default</data>
+            <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data>
+            <data name="shipping/shipping_method" xsi:type="string">Fixed</data>
+            <data name="shippingAddress/dataset" xsi:type="string">UK_address</data>
+            <data name="payment/method" xsi:type="string">checkmo</data>
+            <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedCatalogPage" />
+            <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedProductPage" />
+            <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedShoppingCart" />
+        </variation>
+        <variation name="ApplyCatalogRuleForSimpleProductAndFixedMethod" summary="Apply Catalog Rule For Simple Product And Fixed Shipping Method" ticketId="MAGETWO-23039">
+            <data name="products/0" xsi:type="string">catalogProductSimple::with_fixed_custom_option_price_100</data>
+            <data name="customer/dataset" xsi:type="string">customer_US</data>
+            <data name="catalogRules/0/data/name" xsi:type="string">CatalogPriceRule %isolation%</data>
+            <data name="catalogRules/0/data/is_active" xsi:type="string">Active</data>
+            <data name="catalogRules/0/data/website_ids/option_0" xsi:type="string">Main Website</data>
+            <data name="customer/data/group_id/dataset" xsi:type="string">default</data>
+            <data name="catalogRules/0/data/simple_action" xsi:type="string">Apply as percentage of original</data>
+            <data name="catalogRules/0/data/discount_amount" xsi:type="string">10</data>
+            <data name="cartPrice/sub_total" xsi:type="string">125</data>
+            <data name="cartPrice/grand_total" xsi:type="string">130</data>
+            <data name="productPrice/0/special" xsi:type="string">90</data>
+            <data name="productPrice/0/regular" xsi:type="string">100</data>
+            <data name="productPrice/0/discount_amount" xsi:type="string">10</data>
+            <data name="productPrice/0/sub_total" xsi:type="string">125</data>
+            <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data>
+            <data name="shipping/shipping_method" xsi:type="string">Fixed</data>
+            <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedProductPage" />
+            <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedShoppingCart" />
         </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/DeleteCatalogPriceRuleEntityTest.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/DeleteCatalogPriceRuleEntityTest.php
index a2d0ff9500d4c4c8ac62bf2e4b9f54e6fcc5c4f4..fb4d1946dd2d8183203ef0ad03242e8217d3a82e 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/DeleteCatalogPriceRuleEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/DeleteCatalogPriceRuleEntityTest.php
@@ -10,6 +10,7 @@ use Magento\CatalogRule\Test\Fixture\CatalogRule;
 use Magento\CatalogRule\Test\Page\Adminhtml\CatalogRuleIndex;
 use Magento\CatalogRule\Test\Page\Adminhtml\CatalogRuleNew;
 use Magento\Mtf\TestCase\Injectable;
+use Magento\Customer\Test\Fixture\Customer;
 
 /**
  * Test Creation for Delete CatalogPriceRuleEntity.
@@ -17,6 +18,7 @@ use Magento\Mtf\TestCase\Injectable;
  * Test Flow:
  * Preconditions:
  * 1. Catalog Price Rule is created.
+ * 2. Customer is created if needed.
  * Steps:
  * 1. Log in as default admin user.
  * 2. Go to Marketing > Catalog Price Rules.
@@ -25,7 +27,7 @@ use Magento\Mtf\TestCase\Injectable;
  * 5. Perform all assertions.
  *
  * @group Catalog_Price_Rules
- * @ZephyrId MAGETWO-25211
+ * @ZephyrId MAGETWO-25211, MAGETWO-20431
  */
 class DeleteCatalogPriceRuleEntityTest extends Injectable
 {
@@ -46,7 +48,7 @@ class DeleteCatalogPriceRuleEntityTest extends Injectable
      * @var CatalogRuleNew
      */
     protected $catalogRuleNew;
-    
+
     /**
      * Injection data.
      *
@@ -67,13 +69,18 @@ class DeleteCatalogPriceRuleEntityTest extends Injectable
      *
      * @param CatalogRule $catalogPriceRule
      * @param string $product
+     * @param Customer|null $customer
      * @return array
      */
-    public function test(CatalogRule $catalogPriceRule, $product)
+    public function test(CatalogRule $catalogPriceRule, $product, Customer $customer = null)
     {
         // Precondition
         $catalogPriceRule->persist();
 
+        if ($customer) {
+            $customer->persist();
+        }
+
         $filter = [
             'name' => $catalogPriceRule->getName(),
             'rule_id' => $catalogPriceRule->getId(),
diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/DeleteCatalogPriceRuleEntityTest.xml b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/DeleteCatalogPriceRuleEntityTest.xml
index ed469088ca3c412f064083b81d97da571ccfce8c..6608ccd9a95b55e344a091055d10a9f09d18795b 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/DeleteCatalogPriceRuleEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/DeleteCatalogPriceRuleEntityTest.xml
@@ -7,15 +7,22 @@
  -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
     <testCase name="Magento\CatalogRule\Test\TestCase\DeleteCatalogPriceRuleEntityTest" summary="Delete Catalog Price Rule" ticketId="MAGETWO-25211">
-        <variation name="CatalogRule_Delete_AdminOnly_ProductSimple" summary="Assert that Catalog Price Rule is not applied for simple product">
+        <variation name="CatalogRule_Delete_AdminOnly_ProductSimple" summary="Assert that Catalog Price Rule is not applied for simple product" ticketId="MAGETWO-20431">
             <data name="catalogPriceRule/dataset" xsi:type="string">active_catalog_price_rule_with_conditions</data>
             <data name="product" xsi:type="string">catalogProductSimple::simple_for_salesrule_1</data>
-            <data name="productPrice/0/regular" xsi:type="string">100</data>
+            <data name="customer/dataset" xsi:type="string">customer_US</data>
+            <data name="productPrice/0/regular" xsi:type="number">100</data>
+            <data name="cartPrice/sub_total" xsi:type="number">100</data>
+            <data name="cartPrice/grand_total" xsi:type="number">105</data>
+            <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data>
+            <data name="shipping/shipping_method" xsi:type="string">Fixed</data>
+            <data name="payment/method" xsi:type="string">checkmo</data>
             <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleSuccessDeleteMessage" />
             <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleNotInGrid" />
             <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleNotAppliedCatalogPage" />
             <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleNotAppliedProductPage" />
             <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleNotAppliedShoppingCart" />
+            <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleOnOnepageCheckout" />
         </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/UpdateCatalogPriceRuleEntityTest.xml b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/UpdateCatalogPriceRuleEntityTest.xml
index a9c1ecc9d9e0bc70a289a1414d5f4feb3ce62491..b92ae2a2e14ff26e7d0acf6fa9aa5d34c61370c1 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/UpdateCatalogPriceRuleEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/UpdateCatalogPriceRuleEntityTest.xml
@@ -44,7 +44,7 @@
             <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedCatalogPage" />
             <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedProductPage" />
             <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedShoppingCart" />
-            <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedOnepageCheckout" />
+            <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleOnOnepageCheckout" />
         </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/CatalogRuleConfigurable/Test/TestCase/ApplyConfigurableProductCatalogPriceRulesTest.php b/dev/tests/functional/tests/app/Magento/CatalogRuleConfigurable/Test/TestCase/ApplyConfigurableProductCatalogPriceRulesTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b4a3b0a98d478460b8253031d390cfeaa8dfb29f
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogRuleConfigurable/Test/TestCase/ApplyConfigurableProductCatalogPriceRulesTest.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogRuleConfigurable\Test\TestCase;
+
+use Magento\CatalogRule\Test\TestCase\ApplyCatalogPriceRulesTest;
+use Magento\CatalogRule\Test\Fixture\CatalogRule;
+use Magento\Customer\Test\Fixture\Customer;
+use Magento\Mtf\Util\Command\Cli\Cron;
+use Magento\CatalogRule\Test\Page\Adminhtml\CatalogRuleEdit;
+use Magento\Mtf\TestStep\TestStepFactory;
+use Magento\Mtf\Fixture\FixtureInterface;
+
+/**
+ * Preconditions:
+ * 1. Delete all active catalog price rules.
+ * 2. Create catalog price rule from dataset using Curl.
+ *
+ * Steps:
+ * 1. Apply all created rules.
+ * 2. Create configurable product.
+ * 3. Perform all assertions.
+ *
+ * @group Catalog_Rule_Configurable
+ * @ZephyrId MAGETWO-24780
+ */
+class ApplyConfigurableProductCatalogPriceRulesTest extends ApplyCatalogPriceRulesTest
+{
+    /**
+     * Add attribute_id to catalog price rule.
+     *
+     * @param FixtureInterface $product
+     * @return array
+     */
+    protected function getAttribute(FixtureInterface $product)
+    {
+        if ($product->hasData('configurable_attributes_data')) {
+            $attributes = $product->getDataFieldConfig('configurable_attributes_data')['source']
+                ->getAttributesData()['attribute_key_0'];
+            $result['%attribute_id%'] = $attributes['attribute_code'];
+            $result['%attribute_value%'] = $attributes['options']['option_key_' . $this->promo]['id'];
+            return $result;
+        } else {
+            return parent::getAttribute($product);
+        }
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogRuleConfigurable/Test/TestCase/ApplyConfigurableProductCatalogPriceRulesTest.xml b/dev/tests/functional/tests/app/Magento/CatalogRuleConfigurable/Test/TestCase/ApplyConfigurableProductCatalogPriceRulesTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d156327d2f71d447af996713ae0fd6ab645c780c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogRuleConfigurable/Test/TestCase/ApplyConfigurableProductCatalogPriceRulesTest.xml
@@ -0,0 +1,76 @@
+<?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\CatalogRuleConfigurable\Test\TestCase\ApplyConfigurableProductCatalogPriceRulesTest" summary="Apply Catalog Price Rules">
+        <variation name="ApplyCatalogRuleForComfigurableProductWithOptions1" summary="Apply Catalog Rule For Configurable Product With Promo Simple Product" ticketId="MAGETWO-47186">
+            <data name="products/0" xsi:type="string">configurableProduct::Stellar_Solar_Jacket_SIZE_S</data>
+            <data name="products/1" xsi:type="string">configurableProduct::Stellar_Solar_Jacket_SIZE_M</data>
+            <data name="products/2" xsi:type="string">configurableProduct::Stellar_Solar_Jacket_SIZE_L</data>
+            <data name="promo" xsi:type="string">2</data>
+            <data name="catalogRules/0/data/name" xsi:type="string">Catalog Price Rule %isolation%</data>
+            <data name="catalogRules/0/data/is_active" xsi:type="string">Active</data>
+            <data name="catalogRules/0/data/website_ids/option_0" xsi:type="string">Main Website</data>
+            <data name="catalogRules/0/data/customer_group_ids/option_0" xsi:type="string">NOT LOGGED IN</data>
+            <data name="catalogRules/0/data/rule" xsi:type="string">[Attribute|%attribute_id%|is|%attribute_value%]</data>
+            <data name="catalogRules/0/data/simple_action" xsi:type="string">Apply as fixed amount</data>
+            <data name="catalogRules/0/data/discount_amount" xsi:type="string">0.55</data>
+            <data name="cartPrice/sub_total" xsi:type="string">224.45</data>
+            <data name="cartPrice/grand_total" xsi:type="string">239.45</data>
+            <data name="productPrice/0/special" xsi:type="string">74.45</data>
+            <data name="productPrice/0/sub_total" xsi:type="string">75</data>
+            <data name="productPrice/0/regular" xsi:type="string">No</data>
+            <data name="productPrice/1/special" xsi:type="string">74.45</data>
+            <data name="productPrice/1/sub_total" xsi:type="string">75</data>
+            <data name="productPrice/1/regular" xsi:type="string">No</data>
+            <data name="productPrice/2/special" xsi:type="string">74.45</data>
+            <data name="productPrice/2/sub_total" xsi:type="string">74.45</data>
+            <data name="productPrice/2/regular" xsi:type="string">No</data>
+            <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data>
+            <data name="shipping/shipping_method" xsi:type="string">Fixed</data>
+            <data name="shippingAddress/dataset" xsi:type="string">UK_address</data>
+            <data name="payment/method" xsi:type="string">checkmo</data>
+            <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedProductPage" />
+            <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedShoppingCart" />
+        </variation>
+        <variation name="ApplyCatalogRuleForConfigurableProductWithAssignedSimpleProducts" summary="Apply Catalog Rule For Configurable Product With Custom Options" ticketId="MAGETWO-23042">
+            <data name="products/0" xsi:type="string">configurableProduct::first_product_with_custom_options_and_option_key_1</data>
+            <data name="products/1" xsi:type="string">configurableProduct::first_product_with_custom_options_and_option_key_2</data>
+            <data name="products/2" xsi:type="string">configurableProduct::second_product_with_custom_options_and_option_key_1</data>
+            <data name="products/3" xsi:type="string">configurableProduct::second_product_with_custom_options_and_option_key_2</data>
+            <data name="customer/dataset" xsi:type="string">customer_US</data>
+            <data name="customer/data/group_id/dataset" xsi:type="string">default</data>
+            <data name="catalogRules/0/data/customer_group_ids/option_0" xsi:type="string">NOT LOGGED IN</data>
+            <data name="catalogRules/0/data/name" xsi:type="string">CatalogPriceRule %isolation%</data>
+            <data name="catalogRules/0/data/is_active" xsi:type="string">Active</data>
+            <data name="catalogRules/0/data/website_ids/option_0" xsi:type="string">Main Website</data>
+            <data name="catalogRules/0/data/simple_action" xsi:type="string">Apply as fixed amount</data>
+            <data name="catalogRules/0/data/stop_rules_processing" xsi:type="string">Yes</data>
+            <data name="catalogRules/0/data/discount_amount" xsi:type="string">5</data>
+            <data name="cartPrice/sub_total" xsi:type="string">382</data>
+            <data name="cartPrice/grand_total" xsi:type="string">402</data>
+            <data name="productPrice/0/special" xsi:type="string">15.01</data>
+            <data name="productPrice/0/sub_total" xsi:type="string">86.99</data>
+            <data name="productPrice/0/regular" xsi:type="string">No</data>
+            <data name="productPrice/1/special" xsi:type="string">15.01</data>
+            <data name="productPrice/1/sub_total" xsi:type="string">163.99</data>
+            <data name="productPrice/1/regular" xsi:type="string">No</data>
+            <data name="productPrice/2/special" xsi:type="string">15.01</data>
+            <data name="productPrice/2/sub_total" xsi:type="string">27.01</data>
+            <data name="productPrice/2/regular" xsi:type="string">No</data>
+            <data name="productPrice/3/special" xsi:type="string">15.01</data>
+            <data name="productPrice/3/sub_total" xsi:type="string">104.01</data>
+            <data name="productPrice/3/regular" xsi:type="string">No</data>
+            <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data>
+            <data name="shipping/shipping_method" xsi:type="string">Fixed</data>
+            <data name="shippingAddress/dataset" xsi:type="string">UK_address</data>
+            <data name="payment/method" xsi:type="string">checkmo</data>
+            <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedProductPage" />
+            <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleAppliedShoppingCart" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Advanced/Form.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Advanced/Form.php
index e65838bb7fc55dc5c564a4136f664e831cd65a78..eb7f352edfd93aff427b3a41745823febb977b0b 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Advanced/Form.php
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Advanced/Form.php
@@ -78,6 +78,10 @@ class Form extends ParentForm
             $data = array_merge($data, $data['price']);
             unset($data['price']);
         }
+        if (isset($data['additional_attributes'])) {
+            $data = array_merge($data, $data['additional_attributes']);
+            unset($data['additional_attributes']);
+        }
 
         // Mapping
         $mapping = $this->dataMapping($data);
@@ -86,12 +90,19 @@ class Form extends ParentForm
             /** @var CatalogProductAttribute $attribute */
             $attribute = $fixture->getDataFieldConfig('custom_attribute')['source']->getAttribute();
             $attributeType = $attribute->getFrontendInput();
+            if ($attributeType == 'Text Area') {
+                $attributeType = 'Text Field';
+            }
             $attributeCode = $attribute->getAttributeCode();
         }
         if ($this->hasRender($attributeType)) {
             $element = $this->_rootElement->find(sprintf($this->customAttributeSelector, $attributeCode));
             $arguments = ['fixture' => $fixture, 'element' => $element, 'mapping' => $mapping];
             $this->callRender($attributeType, 'fill', $arguments);
+        } elseif ($attributeType == 'Price') {
+            $value = $data['custom_attribute']['value'];
+            $this->_rootElement->find('#' . $attributeCode)->setValue($value);
+            $this->_rootElement->find('#' . $attributeCode . '_to')->setValue($value);
         } else {
             $this->_fill($mapping, $element);
         }
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Advanced/Form.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Advanced/Form.xml
index 5cbcfdf974099c89fee848d01a73d82183e2f204..ba4035f0dbf8345a13e46c4d3d256dc1c2ae16e0 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Advanced/Form.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Advanced/Form.xml
@@ -25,5 +25,11 @@
         <price_to>
             <selector>#price_to</selector>
         </price_to>
+        <weight_from>
+            <selector>#weight</selector>
+        </weight_from>
+        <weight_to>
+            <selector>#weight_to</selector>
+        </weight_to>
     </fields>
 </mapping>
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Advanced/SearchResultsTitle.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Advanced/SearchResultsTitle.php
new file mode 100644
index 0000000000000000000000000000000000000000..d8ff977e14769804556b6269f7ff02402d98d1f4
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Advanced/SearchResultsTitle.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Test\Block\Advanced;
+
+use Magento\Mtf\Block\Block;
+use Magento\Mtf\Client\Locator;
+
+/**
+ * Block for search results page title.
+ */
+class SearchResultsTitle extends Block
+{
+    /**
+     * CSS selector for block 'Search results for'.
+     *
+     * @var string
+     */
+    protected $searchResultsFor = '[data-ui-id="page-title-wrapper"]';
+
+    /**
+     * Getting actual search query value.
+     *
+     * @return string|null
+     */
+    public function getSearchQuery()
+    {
+        $searchQueryResult = $this->_rootElement->find(sprintf($this->searchResultsFor), Locator::SELECTOR_CSS)
+            ->getText();
+        preg_match("~Search results for: \'(.*)\'~", $searchQueryResult, $matches);
+        $query = isset($matches[1]) ? $matches[1] : null;
+        return $query;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertAdvancedSearchProductByAttribute.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertAdvancedSearchProductByAttribute.php
index be2d2d508a3f9f4d611400eb6bcfb281c35c94bb..6af1b07f132e40a70b7d75d92606513d811ec731 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertAdvancedSearchProductByAttribute.php
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertAdvancedSearchProductByAttribute.php
@@ -34,6 +34,7 @@ class AssertAdvancedSearchProductByAttribute extends AbstractConstraint
      * @param AdvancedSearch $searchPage
      * @param CatalogsearchResult $catalogSearchResult
      * @param FixtureFactory $fixtureFactory
+     * @param int|null $attributeValue
      * @return void
      */
     public function processAssert(
@@ -41,13 +42,14 @@ class AssertAdvancedSearchProductByAttribute extends AbstractConstraint
         InjectableFixture $product,
         AdvancedSearch $searchPage,
         CatalogsearchResult $catalogSearchResult,
-        FixtureFactory $fixtureFactory
+        FixtureFactory $fixtureFactory,
+        $attributeValue = null
     ) {
         $this->fixtureFactory = $fixtureFactory;
         $cmsIndex->open();
         $cmsIndex->getFooterBlock()->openAdvancedSearch();
         $searchForm = $searchPage->getForm();
-        $productSearch = $this->prepareFixture($product);
+        $productSearch = $this->prepareFixture($product, $attributeValue);
 
         $searchForm->fill($productSearch);
         $searchForm->submit();
@@ -63,11 +65,15 @@ class AssertAdvancedSearchProductByAttribute extends AbstractConstraint
      * Preparation of fixture data before comparing.
      *
      * @param InjectableFixture $productSearch
+     * @param int|null $attributeValue
      * @return CatalogProductSimple
      */
-    protected function prepareFixture(InjectableFixture $productSearch)
+    protected function prepareFixture(InjectableFixture $productSearch, $attributeValue)
     {
         $customAttribute = $productSearch->getDataFieldConfig('custom_attribute')['source']->getAttribute();
+        if ($attributeValue !== null) {
+            $customAttribute = ['value' => $attributeValue, 'attribute' => $customAttribute];
+        }
         return $this->fixtureFactory->createByCode(
             'catalogProductSimple',
             ['data' => ['custom_attribute' => $customAttribute]]
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertAdvancedSearchProductResult.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertAdvancedSearchProductResult.php
new file mode 100644
index 0000000000000000000000000000000000000000..1f09f71284c15f598f10c0247570ecfd6edbc049
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertAdvancedSearchProductResult.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Test\Constraint;
+
+use Magento\CatalogSearch\Test\Page\AdvancedResult;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that Advanced Search result page contains only product(s) according to requested from fixture.
+ */
+class AssertAdvancedSearchProductResult extends AbstractConstraint
+{
+    /**
+     * Text for founded product.
+     */
+    const FOUNDED_PRODUCT_MESSAGE = 'Product %s is founded';
+
+    /**
+     * Assert that Advanced Search result page contains only product(s) according to requested from fixture.
+     *
+     * @param array $isVisibleInAdvancedSearch
+     * @param array $allProducts
+     * @param AdvancedResult $resultPage
+     * @return void
+     */
+    public function processAssert(
+        array $isVisibleInAdvancedSearch,
+        array $allProducts,
+        AdvancedResult $resultPage
+    ) {
+        $expectedResult = $this->prepareExpectedResult($isVisibleInAdvancedSearch, $allProducts);
+        $foundedProducts = $this->advancedSearchProducts($resultPage, $allProducts);
+        \PHPUnit_Framework_Assert::assertEquals(
+            $expectedResult,
+            $foundedProducts,
+            'Expected and founded products not the same.'
+            . "\nExpected: " . print_r($expectedResult)
+            . "\nActual: " . print_r($foundedProducts)
+        );
+    }
+
+    /**
+     * Returns array with expected products.
+     *
+     * @param array $isVisibleInAdvancedSearch
+     * @param array $products
+     * @return array
+     */
+    private function prepareExpectedResult(array $isVisibleInAdvancedSearch, array $products)
+    {
+        $expectedResult = [];
+        foreach ($isVisibleInAdvancedSearch as $key => $value) {
+            if ($value == "Yes") {
+                $expectedResult[] = sprintf(self::FOUNDED_PRODUCT_MESSAGE, $products[$key]->getName());
+            }
+        }
+        sort($expectedResult);
+        return $expectedResult;
+    }
+
+    /**
+     * Returns array with found products.
+     *
+     * @param AdvancedResult $resultPage
+     * @param array $allProducts
+     * @return array
+     */
+    private function advancedSearchProducts(AdvancedResult $resultPage, array $allProducts)
+    {
+        $products = $allProducts;
+        $foundedProducts = [];
+        do {
+            $dirtKeys = [];
+            foreach ($allProducts as $key => $product) {
+                $isProductVisible = $resultPage->getListProductBlock()->getProductItem($product)->isVisible();
+                if ($isProductVisible) {
+                    $foundedProducts[] = sprintf(self::FOUNDED_PRODUCT_MESSAGE, $products[$key]->getName());
+                    $dirtKeys[] = $key;
+                }
+            }
+            foreach ($dirtKeys as $key) {
+                unset($products[$key]);
+            }
+        } while ($resultPage->getBottomToolbar()->nextPage() && (count($products) > 0));
+        sort($foundedProducts);
+        return $foundedProducts;
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'All products are involved in the search were found successfully.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertCatalogSearchQueryLength.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertCatalogSearchQueryLength.php
new file mode 100644
index 0000000000000000000000000000000000000000..831becb6f73c91fafe8e6cd57bf396cd6051647c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertCatalogSearchQueryLength.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Test\Constraint;
+
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\CatalogSearch\Test\Page\CatalogsearchResult;
+
+/**
+ * Assert that search query length truncated to 128 symbols.
+ */
+class AssertCatalogSearchQueryLength extends AbstractConstraint
+{
+    /**
+     * Assert that search query length truncated to 128 symbols.
+     *
+     * @param CatalogsearchResult $catalogSearchResult
+     * @return void
+     */
+    public function processAssert(CatalogsearchResult $catalogSearchResult)
+    {
+        \PHPUnit_Framework_Assert::assertEquals(
+            mb_strlen($catalogSearchResult->getSearchResultsTitleBlock()->getSearchQuery()),
+            128,
+            'Search query length is not truncated to 128 symbols.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Search query truncated to 128 symbols.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchAttributeTest.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchAttributeTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c2a719752e8d93f27470029963ce12b329ce89ef
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchAttributeTest.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Test\Constraint;
+
+use Magento\CatalogSearch\Test\Page\AdvancedSearch;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert advanced attribute is present(or absent) in Advanced Search Page.
+ */
+class AssertSearchAttributeTest extends AbstractConstraint
+{
+    /**
+     * Assert advanced attribute is present(or absent) in Advanced Search Page.
+     *
+     * @param AdvancedSearch $advancedSearch
+     * @param array $attributeForSearch
+     * @return void
+     */
+    public function processAssert(
+        AdvancedSearch $advancedSearch,
+        array $attributeForSearch
+    ) {
+        $advancedSearch->open();
+        $availableAttributes = $advancedSearch->getForm()->getFormLabels();
+        if (isset($attributeForSearch['isVisible'])) {
+            \PHPUnit_Framework_Assert::assertTrue(
+                (false !== array_search($attributeForSearch['name'], $availableAttributes)),
+                'Attribute ' . $attributeForSearch['name'] . 'was not found in Advanced Search Page.'
+            );
+        } else {
+            \PHPUnit_Framework_Assert::assertTrue(
+                (false == array_search($attributeForSearch['name'], $availableAttributes)),
+                'Attribute ' . $attributeForSearch['name'] . ' was found in Advanced Search Page.'
+            );
+        }
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Attribute was found in Advanced Search Page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/CatalogsearchResult.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/CatalogsearchResult.xml
index 49ee4cd35e9c8878489f1621b281be74af1351c5..bc8931b7b325dc057f20b9706ad6e0c70882b273 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/CatalogsearchResult.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/CatalogsearchResult.xml
@@ -10,5 +10,6 @@
         <block name="listProductBlock" class="Magento\Catalog\Test\Block\Product\ListProduct" locator=".search.results" strategy="css selector" />
         <block name="bottomToolbar" class="Magento\Catalog\Test\Block\Product\ProductList\BottomToolbar" locator=".//*[contains(@class,'toolbar-products')][2]" strategy="xpath" />
         <block name="searchResultBlock" class="Magento\CatalogSearch\Test\Block\Advanced\Result" locator=".column.main" strategy="css selector" />
+        <block name="searchResultsTitleBlock" class="Magento\CatalogSearch\Test\Block\Advanced\SearchResultsTitle" locator=".page-title-wrapper" strategy="css selector" />
     </page>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest.php
index c845e7f0bfe85958c20136ebcf0da30f53d31874..5848a6cfd7ea6ab178cfdfa8263e0a7c0bbf92a6 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest.php
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest.php
@@ -20,7 +20,7 @@ use Magento\Mtf\TestCase\Injectable;
  * 3. Perform all assertions.
  *
  * @group Search_Frontend
- * @ZephyrId MAGETWO-25095
+ * @ZephyrId MAGETWO-25095, MAGETWO-36542
  */
 class SearchEntityResultsTest extends Injectable
 {
@@ -51,11 +51,12 @@ class SearchEntityResultsTest extends Injectable
      * Run searching result test.
      *
      * @param CatalogSearchQuery $catalogSearch
+     * @param string|null $queryLength
      * @return void
      */
-    public function test(CatalogSearchQuery $catalogSearch)
+    public function test(CatalogSearchQuery $catalogSearch, $queryLength = null)
     {
         $this->cmsIndex->open();
-        $this->cmsIndex->getSearchBlock()->search($catalogSearch->getQueryText());
+        $this->cmsIndex->getSearchBlock()->search($catalogSearch->getQueryText(), $queryLength);
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest.xml
index 3f8e5191a80f745ae5f5204c5d2cb1361fe3bd09..7851e6b697d3efcd193bc8340e3d4517574d2676 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest.xml
@@ -60,5 +60,27 @@
             <constraint name="Magento\CatalogSearch\Test\Constraint\AssertCatalogSearchNoResultMessage" />
             <constraint name="Magento\CatalogSearch\Test\Constraint\AssertCatalogSearchNoResult" />
         </variation>
+        <variation name="SearchEntityResultsTestVariation12" summary="Search for simple product name using 2 symbols query length" ticketId="MAGETWO-36542">
+            <data name="catalogSearch/data/query_text/value" xsi:type="string">catalogProductSimple::default::name</data>
+            <data name="queryLength" xsi:type="string">2</data>
+            <constraint name="Magento\CatalogSearch\Test\Constraint\AssertCatalogSearchNoResultMessage" />
+            <constraint name="Magento\CatalogSearch\Test\Constraint\AssertCatalogSearchNoResult" />
+        </variation>
+        <variation name="SearchEntityResultsTestVariation13" summary="Search for simple product name using 3 symbols query length" ticketId="MAGETWO-36542">
+            <data name="catalogSearch/data/query_text/value" xsi:type="string">catalogProductSimple::default::name</data>
+            <data name="queryLength" xsi:type="string">3</data>
+            <constraint name="Magento\CatalogSearch\Test\Constraint\AssertProductCanBeOpenedFromSearchResult" />
+        </variation>
+        <variation name="SearchEntityResultsTestVariation14" summary="Search for simple product name using 128 symbols query length" ticketId="MAGETWO-36542">
+            <data name="catalogSearch/data/query_text/value" xsi:type="string">catalogProductSimple::product_with_long_name::name</data>
+            <data name="queryLength" xsi:type="string">128</data>
+            <constraint name="Magento\CatalogSearch\Test\Constraint\AssertProductCanBeOpenedFromSearchResult" />
+        </variation>
+        <variation name="SearchEntityResultsTestVariation15" summary="Search for simple product name using 129 symbols query length" ticketId="MAGETWO-36542">
+            <data name="catalogSearch/data/query_text/value" xsi:type="string">catalogProductSimple::product_with_long_name::name</data>
+            <data name="queryLength" xsi:type="string">129</data>
+            <constraint name="Magento\CatalogSearch\Test\Constraint\AssertCatalogSearchQueryLength" />
+            <constraint name="Magento\CatalogSearch\Test\Constraint\AssertProductCanBeOpenedFromSearchResult" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Shipping.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Shipping.php
index a10d28f5e70e35a6e64abf63bf5f69df99823eb8..036f984441457cc2150597a5c3cc79f6e91b52c6 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Shipping.php
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Shipping.php
@@ -51,6 +51,13 @@ class Shipping extends Form
      */
     protected $estimationFields = ['country_id', 'region_id', 'region', 'postcode'];
 
+    /**
+     * Selector for top destinations in country field.
+     *
+     * @var string
+     */
+    private $topOptions = './option[@value="delimiter"]/preceding-sibling::option[string(@value)]';
+
     /**
      * Block wait element.
      *
@@ -59,7 +66,7 @@ class Shipping extends Form
     protected $blockWaitElement = '._block-content-loading';
 
     /**
-     * Get shipping price selector for exclude and include price
+     * Get shipping price selector for exclude and include price.
      *
      * @var string
      */
@@ -77,6 +84,29 @@ class Shipping extends Form
         }
     }
 
+    /**
+     * Get countries displayed at the top of country element.
+     *
+     * @return array
+     */
+    public function getTopCountries()
+    {
+        $this->openEstimateShippingAndTax();
+        $mapping = $this->dataMapping(array_flip(['country_id']));
+        $countryField = $this->getElement($this->_rootElement, $mapping['country_id']);
+        $this->_rootElement->waitUntil(
+            function () use ($countryField) {
+                return $countryField->isVisible() ? true : null;
+            }
+        );
+        return array_map(
+            function ($option) {
+                return $option->getAttribute('value');
+            },
+            $countryField->getElements($this->topOptions, Locator::SELECTOR_XPATH)
+        );
+    }
+
     /**
      * Select shipping method.
      *
@@ -168,7 +198,7 @@ class Shipping extends Form
     }
 
     /**
-     * Wait for common shipping price block to appear
+     * Wait for common shipping price block to appear.
      *
      * @return void
      */
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 fe844bc08b0017b2aa1cabfe4a7882b3733c118a..6b7016f1b99bfd4123fe7ca80d8727b9bc6bff2d 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
@@ -16,7 +16,7 @@ use Magento\Mtf\Client\Locator;
 class Shipping extends Form
 {
     /**
-     * CSS Selector for "New Address" button
+     * CSS Selector for "New Address" button.
      *
      * @var string
      */
@@ -69,6 +69,65 @@ class Shipping extends Form
      */
     private $selectedShippingAddressBlock = '.selected-item';
 
+    /**
+     * Email instructions selector.
+     *
+     * @var string
+     */
+    private $emailInstructions = '#customer-email-fieldset .note span';
+
+    /**
+     * Email tooltip button selector.
+     *
+     * @var string
+     */
+    private $emailTooltipButton = '#customer-email-fieldset .field-tooltip-action';
+
+    /**
+     * Email tooltip content selector.
+     *
+     * @var string
+     */
+    private $emailTooltipContent = '#customer-email-fieldset .field-tooltip-content';
+
+    /**
+     * Email error selector.
+     *
+     * @var string
+     */
+    private $emailError = '#customer-email-error';
+
+    /**
+     * Get email error.
+     *
+     * @return string
+     */
+    public function getEmailError()
+    {
+        return $this->_rootElement->find($this->emailError)->getText();
+    }
+
+    /**
+     * Get email tooltip.
+     *
+     * @return string
+     */
+    public function getEmailTooltip()
+    {
+        $this->_rootElement->find($this->emailTooltipButton)->click();
+        return $this->_rootElement->find($this->emailTooltipContent)->getText();
+    }
+
+    /**
+     * Get email instructions.
+     *
+     * @return string
+     */
+    public function getEmailInstructions()
+    {
+        return $this->_rootElement->find($this->emailInstructions)->getText();
+    }
+
     /**
      * Click on "New Address" button.
      *
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/Method.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/Method.php
index 24bddf79c1a07c9205e0b22426946e11b92d0489..cbddb26781479302f962141723886df497d43237 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/Method.php
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/Method.php
@@ -21,6 +21,13 @@ class Method extends Block
      */
     protected $shippingMethod = './/tbody//tr[td[contains(., "%s")] and td[contains(., "%s")]]//input';
 
+    /**
+     * Shipping method amount selector.
+     *
+     * @var string
+     */
+    private $shippingMethodAmount = './/tr[td[contains(., "%s")] and td[contains(., "%s")]]//span[@class="price"]';
+
     /**
      * Continue checkout button.
      *
@@ -108,4 +115,16 @@ class Method extends Block
             }
         );
     }
+
+    /**
+     * Get shipping method amount.
+     *
+     * @param array $method
+     * @return string
+     */
+    public function getShippingMethodAmount(array $method)
+    {
+        $selector = sprintf($this->shippingMethodAmount, $method['shipping_method'], $method['shipping_service']);
+        return $this->_rootElement->find($selector, Locator::SELECTOR_XPATH)->getText();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddToCartButtonAbsentOnCategoryPage.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddToCartButtonAbsentOnCategoryPage.php
new file mode 100644
index 0000000000000000000000000000000000000000..183b28d9c46d24bbd6a6cd1de7cb04635d7e0c22
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddToCartButtonAbsentOnCategoryPage.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Checkout\Test\Constraint;
+
+use Magento\Mtf\Fixture\InjectableFixture;
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Fixture\Category;
+use Magento\Catalog\Test\Page\Category\CatalogCategoryView;
+use Magento\Catalog\Test\Page\Product\CatalogProductView;
+use Magento\Cms\Test\Page\CmsIndex;
+
+/**
+ * Checks that "Add to Cart" button is absent on category page.
+ */
+class AssertAddToCartButtonAbsentOnCategoryPage extends AbstractConstraint
+{
+    /**
+     * Assert that "Add to Cart" button is absent on category page.
+     *
+     * @param InjectableFixture $product
+     * @param CmsIndex $cmsIndex
+     * @param CatalogCategoryView $catalogCategoryView
+     * @param Category|null $category [optional]
+     * @return void
+     */
+    public function processAssert(
+        InjectableFixture $product,
+        CmsIndex $cmsIndex,
+        CatalogCategoryView $catalogCategoryView,
+        Category $category = null
+    ) {
+        $cmsIndex->open();
+        $categoryName = $category === null ? $product->getCategoryIds()[0] : $category->getName();
+        $cmsIndex->getTopmenu()->selectCategoryByName($categoryName);
+
+        $isProductVisible = $catalogCategoryView->getListProductBlock()->getProductItem($product)->isVisible();
+        while (!$isProductVisible && $catalogCategoryView->getBottomToolbar()->nextPage()) {
+            $isProductVisible = $catalogCategoryView->getListProductBlock()->getProductItem($product)->isVisible();
+        }
+        \PHPUnit_Framework_Assert::assertTrue($isProductVisible, 'Product is absent on category page.');
+
+        \PHPUnit_Framework_Assert::assertFalse(
+            $catalogCategoryView->getListProductBlock()->getProductItem($product)->isVisibleAddToCardButton(),
+            'Button "Add to Cart" is present on category page.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Button "Add to Cart" is absent on product page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddToCartButtonAbsentOnProductPage.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddToCartButtonAbsentOnProductPage.php
new file mode 100644
index 0000000000000000000000000000000000000000..fb7db2c361595d9e7caea6dd71689725d64b5545
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddToCartButtonAbsentOnProductPage.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Checkout\Test\Constraint;
+
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Mtf\Fixture\InjectableFixture;
+use Magento\Mtf\Client\BrowserInterface;
+use Magento\Catalog\Test\Page\Product\CatalogProductView;
+
+/**
+ * Checks that "Add to Cart" button is absent on product page.
+ */
+class AssertAddToCartButtonAbsentOnProductPage extends AbstractConstraint
+{
+    /**
+     * Assert that "Add to Cart" button is absent on product page.
+     *
+     * @param BrowserInterface $browser
+     * @param InjectableFixture $product
+     * @param CatalogProductView $catalogProductView
+     * @return void
+     */
+    public function processAssert(
+        BrowserInterface $browser,
+        InjectableFixture $product,
+        CatalogProductView $catalogProductView
+    ) {
+        $browser->open($_ENV['app_frontend_url'] . $product->getUrlKey() . '.html');
+        \PHPUnit_Framework_Assert::assertFalse(
+            $catalogProductView->getViewBlock()->isVisibleAddToCardButton(),
+            'Button "Add to Cart" is present on product page.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Button "Add to Cart" is absent on product page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddToCartButtonPresentOnCategoryPage.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddToCartButtonPresentOnCategoryPage.php
new file mode 100644
index 0000000000000000000000000000000000000000..dfa8420d70fa788a3f229ef30acf31d2f6d36cd7
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddToCartButtonPresentOnCategoryPage.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Checkout\Test\Constraint;
+
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Mtf\Fixture\InjectableFixture;
+use Magento\Catalog\Test\Fixture\Category;
+use Magento\Catalog\Test\Page\Category\CatalogCategoryView;
+use Magento\Cms\Test\Page\CmsIndex;
+
+/**
+ * Checks that "Add to Cart" button is visible on category page.
+ */
+class AssertAddToCartButtonPresentOnCategoryPage extends AbstractConstraint
+{
+    /**
+     * Assert that "Add to Cart" button is present on category page.
+     *
+     * @param InjectableFixture $product
+     * @param CmsIndex $cmsIndex
+     * @param CatalogCategoryView $catalogCategoryView
+     * @param Category|null $category [optional]
+     * @return void
+     */
+    public function processAssert(
+        InjectableFixture $product,
+        CmsIndex $cmsIndex,
+        CatalogCategoryView $catalogCategoryView,
+        Category $category = null
+    ) {
+        $cmsIndex->open();
+        $categoryName = $category === null ? $product->getCategoryIds()[0] : $category->getName();
+        $cmsIndex->getTopmenu()->selectCategoryByName($categoryName);
+
+        $isProductVisible = $catalogCategoryView->getListProductBlock()->getProductItem($product)->isVisible();
+        while (!$isProductVisible && $catalogCategoryView->getBottomToolbar()->nextPage()) {
+            $isProductVisible = $catalogCategoryView->getListProductBlock()->getProductItem($product)->isVisible();
+        }
+        \PHPUnit_Framework_Assert::assertTrue($isProductVisible, 'Product is absent on category page.');
+
+        \PHPUnit_Framework_Assert::assertTrue(
+            $catalogCategoryView->getListProductBlock()->getProductItem($product)->isVisibleAddToCardButton(),
+            'Button "Add to Cart" is absent on category page.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Button "Add to Cart" is present on category page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddToCartButtonPresentOnProductPage.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddToCartButtonPresentOnProductPage.php
new file mode 100644
index 0000000000000000000000000000000000000000..1590c98488b2ada80f5a141d8551c366863109e3
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddToCartButtonPresentOnProductPage.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Checkout\Test\Constraint;
+
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Mtf\Fixture\InjectableFixture;
+use Magento\Mtf\Client\BrowserInterface;
+use Magento\Catalog\Test\Page\Product\CatalogProductView;
+
+/**
+ * Checks that "Add to Cart" button is visible on product page.
+ */
+class AssertAddToCartButtonPresentOnProductPage extends AbstractConstraint
+{
+    /**
+     * Assert that "Add to Cart" button is present on product page.
+     *
+     * @param BrowserInterface $browser
+     * @param InjectableFixture $product
+     * @param CatalogProductView $catalogProductView
+     * @return void
+     */
+    public function processAssert(
+        BrowserInterface $browser,
+        InjectableFixture $product,
+        CatalogProductView $catalogProductView
+    ) {
+        $browser->open($_ENV['app_frontend_url'] . $product->getUrlKey() . '.html');
+        \PHPUnit_Framework_Assert::assertTrue(
+            $catalogProductView->getViewBlock()->isVisibleAddToCardButton(),
+            'Button "Add to Cart" is absent on product page.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Button "Add to Cart" is present on product page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.php
new file mode 100644
index 0000000000000000000000000000000000000000..d549e14c7afd94bc35d2540662012fd9f970b872
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.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\CheckoutCart;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that success message about canceled order is present and correct.
+ */
+class AssertCancelSuccessMessageInShoppingCart extends AbstractConstraint
+{
+    /**
+     * Cancel success message text.
+     */
+    const SUCCESS_MESSAGE = 'Payment was canceled.';
+
+    /**
+     * Assert that success message about canceled order is present and correct.
+     *
+     * @param CheckoutCart $checkoutCart
+     * @return void
+     */
+    public function processAssert(CheckoutCart $checkoutCart)
+    {
+        $actualMessage = $checkoutCart->getMessagesBlock()->getSuccessMessage();
+        \PHPUnit_Framework_Assert::assertEquals(
+            self::SUCCESS_MESSAGE,
+            $actualMessage,
+            'Success message is not present or has wrong text.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Cancel success message is present or has a correct text.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertEmailErrorValidationMessage.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertEmailErrorValidationMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..01941682c328cdc5b5176e75245be65148f5bf84
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertEmailErrorValidationMessage.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;
+
+/**
+ * Assert that email validation message is correct.
+ */
+class AssertEmailErrorValidationMessage extends AbstractConstraint
+{
+    /**
+     * Email validation message.
+     */
+    const EMAIL_VALIDATION_MESSAGE = 'Please enter a valid email address (Ex: johndoe@domain.com).';
+
+    /**
+     * Assert that email validation message is correct.
+     *
+     * @param CheckoutOnepage $checkoutOnepage
+     * @return void
+     */
+    public function processAssert(
+        CheckoutOnepage $checkoutOnepage
+    ) {
+        \PHPUnit_Framework_Assert::assertEquals(
+            self::EMAIL_VALIDATION_MESSAGE,
+            $checkoutOnepage->getShippingBlock()->getEmailError(),
+            'Email validation message is not correct.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Email validation message is correct.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertEmailToolTips.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertEmailToolTips.php
new file mode 100644
index 0000000000000000000000000000000000000000..974d1ba290da82ad9c0002d51ad0e7d52ea89ed4
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertEmailToolTips.php
@@ -0,0 +1,58 @@
+<?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;
+
+/**
+ * Assert that email field tooltips are present.
+ */
+class AssertEmailToolTips extends AbstractConstraint
+{
+    /**
+     * Email tooltip message.
+     */
+    const EMAIL_TOOLTIP = 'We\'ll send your order confirmation here.';
+
+    /**
+     * Email instructions message.
+     */
+    const EMAIL_INSTRUCTIONS = 'You can create an account after checkout.';
+
+    /**
+     * Assert that email field tooltips are present.
+     *
+     * @param CheckoutOnepage $checkoutOnepage
+     * @return void
+     */
+    public function processAssert(
+        CheckoutOnepage $checkoutOnepage
+    ) {
+        \PHPUnit_Framework_Assert::assertEquals(
+            self::EMAIL_TOOLTIP,
+            $checkoutOnepage->getShippingBlock()->getEmailTooltip(),
+            'Email tooltip is not correct.'
+        );
+
+        \PHPUnit_Framework_Assert::assertEquals(
+            self::EMAIL_INSTRUCTIONS,
+            $checkoutOnepage->getShippingBlock()->getEmailInstructions(),
+            'Email instructions are not correct.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Email field tooltips are present.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertTopDestinationsInSelect.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertTopDestinationsInSelect.php
new file mode 100644
index 0000000000000000000000000000000000000000..340cdef2c0ea73044d066fcc1d6d66dd5c68520a
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertTopDestinationsInSelect.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Checkout\Test\Constraint;
+
+use Magento\Checkout\Test\Page\CheckoutCart;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that countries selected as Top Destinations are at the top in Estimate Shipping and Tax block.
+ */
+class AssertTopDestinationsInSelect extends AbstractConstraint
+{
+    /**
+     * Assert top destinations in select in Estimate Shipping and Tax block.
+     *
+     * @param CheckoutCart $checkoutCart
+     * @param array $topDestinations
+     * @return void
+     */
+    public function processAssert(CheckoutCart $checkoutCart, array $topDestinations)
+    {
+        $checkoutCart->open();
+        \PHPUnit_Framework_Assert::assertEquals(
+            $topDestinations,
+            $checkoutCart->getShippingBlock()->getTopCountries(),
+            'Top countries are different from the ones selected as Top Destinations.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Countries selected as Top Destinations are at the top in select.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.php
index e41af50cca9f624c489dd8af497d601f0d41a426..0a11e63a8c2fb9825d25b2b9915404745a0b95b1 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.php
@@ -15,13 +15,13 @@ use Magento\Mtf\TestCase\Injectable;
 
 /**
  * Preconditions:
- * 1. All type products is created
+ * 1. All type products is created.
  *
  * Steps:
- * 1. Navigate to frontend
- * 2. Open test product page
- * 3. Add to cart test product
- * 4. Perform all asserts
+ * 1. Navigate to frontend.
+ * 2. Open test product page.
+ * 3. Add to cart test product.
+ * 4. Perform all asserts.
  *
  * @group Shopping_Cart
  * @ZephyrId MAGETWO-25382
@@ -34,35 +34,42 @@ class AddProductsToShoppingCartEntityTest extends Injectable
     /* end tags */
 
     /**
-     * Browser interface
+     * Browser interface.
      *
      * @var BrowserInterface
      */
-    protected $browser;
+    private $browser;
 
     /**
-     * Fixture factory
+     * Fixture factory.
      *
      * @var FixtureFactory
      */
-    protected $fixtureFactory;
+    private $fixtureFactory;
 
     /**
-     * Catalog product view page
+     * Catalog product view page.
      *
      * @var CatalogProductView
      */
-    protected $catalogProductView;
+    private $catalogProductView;
 
     /**
-     * Checkout cart page
+     * Checkout cart page.
      *
      * @var CheckoutCart
      */
     protected $cartPage;
 
     /**
-     * Prepare test data
+     * Config settings.
+     *
+     * @var string
+     */
+    private $configData;
+
+    /**
+     * Prepare test data.
      *
      * @param BrowserInterface $browser
      * @param FixtureFactory $fixtureFactory
@@ -83,15 +90,21 @@ class AddProductsToShoppingCartEntityTest extends Injectable
     }
 
     /**
-     * Run test add products to shopping cart
+     * Run test add products to shopping cart.
      *
      * @param array $productsData
      * @param array $cart
+     * @param string|null $configData [optional]
      * @return array
      */
-    public function test(array $productsData, array $cart)
+    public function test(array $productsData, array $cart, $configData = null)
     {
         // Preconditions
+        $this->configData = $configData;
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData]
+        )->run();
         $products = $this->prepareProducts($productsData);
 
         // Steps
@@ -102,7 +115,7 @@ class AddProductsToShoppingCartEntityTest extends Injectable
     }
 
     /**
-     * Create products
+     * Create products.
      *
      * @param array $productList
      * @return array
@@ -119,7 +132,7 @@ class AddProductsToShoppingCartEntityTest extends Injectable
     }
 
     /**
-     * Add products to cart
+     * Add products to cart.
      *
      * @param array $products
      * @return void
@@ -132,4 +145,17 @@ class AddProductsToShoppingCartEntityTest extends Injectable
         );
         $addToCartStep->run();
     }
+
+    /**
+     * Reset config settings to default.
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData, 'rollback' => true]
+        )->run();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml
index cac5e0a9c2182a05e8925a375396b7fe6f610a99..616f10aef0878e4d1b4d2425876901c7c2386665 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml
@@ -116,5 +116,18 @@
             <constraint name="Magento\Checkout\Test\Constraint\AssertGrandTotalInShoppingCart" />
             <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" />
         </variation>
+        <variation name="AddProductsToShoppingCartEntityTestVariation9" summary="Verify Top Destinations for Country Options configuration applied in shopping cart" ticketId="MAGETWO-38700">
+            <data name="productsData/0" xsi:type="string">catalogProductSimple::product_10_dollar</data>
+            <data name="configData" xsi:type="string">top_destinations_DE_ES_GB</data>
+            <data name="cart/data/grand_total" xsi:type="string">15.00</data>
+            <data name="cart/data/subtotal" xsi:type="string">10.00</data>
+            <data name="topDestinations" xsi:type="array">
+                <item name="0" xsi:type="string">DE</item>
+                <item name="1" xsi:type="string">ES</item>
+                <item name="2" xsi:type="string">GB</item>
+            </data>
+            <data name="issue" xsi:type="string">MAGETWO-61592 - [Shopping Cart] Top destinations are not displayed in the shopping cart summary</data>
+            <constraint name="Magento\Checkout\Test\Constraint\AssertTopDestinationsInSelect" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.xml
index 1b6f78148a129a1bd575fe12a91b99e7cbde87aa..0e40b7d5b2c15c2f342f8390e05b61d9ef771cf8 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.xml
@@ -151,7 +151,7 @@
             <data name="products/0" xsi:type="string">catalogProductVirtual::product_50_dollar</data>
             <data name="salesRule" xsi:type="string">active_sales_rule_with_fixed_price_discount_coupon</data>
             <data name="customer/dataset" xsi:type="string">default</data>
-            <data name="billingAddress/dataset" xsi:type="string">UK_address</data>
+            <data name="billingAddress/dataset" xsi:type="string">UK_address_without_email</data>
             <data name="checkoutMethod" xsi:type="string">guest</data>
             <data name="prices" xsi:type="array">
                 <item name="grandTotal" xsi:type="string">0.00</item>
@@ -170,7 +170,7 @@
             <data name="tag" xsi:type="string">severity:S1</data>
             <data name="products/0" xsi:type="string">catalogProductSimple::product_with_qty_25</data>
             <data name="checkoutMethod" xsi:type="string">guest</data>
-            <data name="shippingAddress/dataset" xsi:type="string">UK_address</data>
+            <data name="shippingAddress/dataset" xsi:type="string">UK_address_without_email</data>
             <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data>
             <data name="shipping/shipping_method" xsi:type="string">Fixed</data>
             <data name="prices" xsi:type="array">
@@ -223,24 +223,25 @@
         </variation>
         <variation name="OnePageCheckoutTestVariation10" summary="One Page Checkout with all product types">
             <data name="tag" xsi:type="string">stable:no, severity:S0</data>
-            <data name="products/0" xsi:type="string">catalogProductVirtual::default</data>
-            <data name="products/1" xsi:type="string">downloadableProduct::with_two_separately_links</data>
-            <data name="products/2" xsi:type="string">configurableProduct::with_one_option</data>
-            <data name="products/3" xsi:type="string">bundleProduct::bundle_fixed_100_dollar_product</data>
-            <data name="products/4" xsi:type="string">catalogProductSimple::simple_10_dollar</data>
-            <data name="products/5" xsi:type="string">groupedProduct::three_simple_products</data>
+            <data name="products/0" xsi:type="string">catalogProductVirtual::buy_all</data>
+            <data name="products/1" xsi:type="string">downloadableProduct::with_two_separately_links_buy_all</data>
+            <data name="products/2" xsi:type="string">configurableProduct::with_one_option_buy_all</data>
+            <data name="products/3" xsi:type="string">bundleProduct::bundle_fixed_100_dollar_product_buy_all</data>
+            <data name="products/4" xsi:type="string">catalogProductSimple::simple_10_dollar_buy_all</data>
+            <data name="products/5" xsi:type="string">groupedProduct::three_simple_products_buy_all</data>
             <data name="customer/dataset" xsi:type="string">default</data>
             <data name="checkoutMethod" xsi:type="string">login</data>
             <data name="shippingAddress/dataset" xsi:type="string">UK_address_without_email</data>
             <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data>
             <data name="shipping/shipping_method" xsi:type="string">Fixed</data>
             <data name="prices" xsi:type="array">
-                <item name="grandTotal" xsi:type="string">2118.43</item>
+                <item name="grandTotal" xsi:type="string">3558.43</item>
             </data>
             <data name="payment/method" xsi:type="string">checkmo</data>
-            <data name="configData" xsi:type="string">checkmo</data>
+            <data name="configData" xsi:type="string">checkmo, display_out_of_stock</data>
             <constraint name="Magento\Customer\Test\Constraint\AssertCustomerDefaultAddressFrontendAddressBook" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" />
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductsOutOfStock" />
         </variation>
         <variation name="OnePageCheckoutUsingSingInLink" summary="Login during checkout using 'Sign In' link" ticketId="MAGETWO-42547">
             <data name="tag" xsi:type="string">severity:S1</data>
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0f9efecc46ea4296444b03ca198da11cff5c0bce
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Checkout\Test\TestCase;
+
+use Magento\Catalog\Test\Fixture\CatalogProductSimple;
+use Magento\Catalog\Test\Page\Product\CatalogProductView;
+use Magento\Checkout\Test\Page\CheckoutCart;
+use Magento\Checkout\Test\Page\CheckoutOnepage;
+use Magento\Customer\Test\Fixture\Customer;
+use Magento\Mtf\Client\BrowserInterface;
+use Magento\Mtf\TestCase\Injectable;
+
+/**
+ * Precondition:
+ * 1. Simple product is created
+ * 2. Clear shopping cart
+ *
+ * Steps:
+ * 1. Go to Storefront as Guest
+ * 2. Add simple product to shopping cart
+ * 3. Go to Checkout
+ * 4. Enter the email according to the data set
+ * 5. Perform assertions
+ *
+ * @ZephyrId MAGETWO-42543
+ */
+class ValidateEmailOnCheckoutTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    /* end tags */
+
+    /**
+     * Validate email on checkout.
+     *
+     * @param CatalogProductSimple $product
+     * @param CheckoutCart $cartPage
+     * @param CatalogProductView $catalogProductView
+     * @param BrowserInterface $browser
+     * @param CheckoutOnepage $checkoutOnepage
+     * @param Customer $customer
+     * @return void
+     */
+    public function test(
+        CatalogProductSimple $product,
+        CheckoutCart $cartPage,
+        CatalogProductView $catalogProductView,
+        BrowserInterface $browser,
+        CheckoutOnepage $checkoutOnepage,
+        Customer $customer
+    ) {
+        //Preconditions
+        $product->persist();
+
+        $cartPage->open();
+        $cartPage->getCartBlock()->clearShoppingCart();
+
+        //Steps
+        $browser->open($_ENV['app_frontend_url'] . $product->getUrlKey() . '.html');
+        $productView = $catalogProductView->getViewBlock();
+        $productView->fillOptions($product);
+        $productView->setQty($product->getCheckoutData()['qty']);
+        $productView->clickAddToCart();
+        $catalogProductView->getMessagesBlock()->waitSuccessMessage();
+
+        $checkoutOnepage->open();
+        $checkoutOnepage->getShippingBlock()->fill($customer);
+        $checkoutOnepage->getShippingMethodBlock()->clickContinue();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2e32affe4fbcaf645698208d29a86f5d1b85c422
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/ValidateEmailOnCheckoutTest.xml
@@ -0,0 +1,27 @@
+<?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\ValidateEmailOnCheckoutTest" summary="Email validation for Guest on checkout flow" ticketId="MAGETWO-42543">
+        <variation name="ValidateEmailOnCheckoutTestVariation1">
+            <data name="customer/data/email" xsi:type="string">johndoe</data>
+            <data name="customer/data/firstname" xsi:type="string">John</data>
+            <constraint name="Magento\Checkout\Test\Constraint\AssertEmailErrorValidationMessage" />
+            <constraint name="Magento\Checkout\Test\Constraint\AssertEmailToolTips" />
+        </variation>
+        <variation name="ValidateEmailOnCheckoutTestVariation2">
+            <data name="customer/data/email" xsi:type="string">johndoe#example.com</data>
+            <data name="customer/data/firstname" xsi:type="string">John</data>
+            <constraint name="Magento\Checkout\Test\Constraint\AssertEmailErrorValidationMessage" />
+        </variation>
+        <variation name="ValidateEmailOnCheckoutTestVariation3">
+            <data name="customer/data/email" xsi:type="string">johndoe@example.c</data>
+            <data name="customer/data/firstname" xsi:type="string">John</data>
+            <constraint name="Magento\Checkout\Test\Constraint\AssertEmailErrorValidationMessage" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php
index 720965212ad38d6d249d7ef4f1634e2c43f5deb2..c695b96cf687b9b8f1e2f7d88ab16f05a6185576 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/FillBillingInformationStep.php
@@ -112,7 +112,7 @@ class FillBillingInformationStep implements TestStepInterface
      */
     public function run()
     {
-        $billingAddress = null;
+        $billingAddress = $this->billingAddress;
         if ($this->billingCheckboxState) {
             $this->assertBillingAddressCheckbox->processAssert($this->checkoutOnepage, $this->billingCheckboxState);
         }
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/di.xml
index 9f13d8dddb9a768442f7051a6e11be16f7df9233..0a0622936a23d7688cf0e94b61ebc2ef56d052f4 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/di.xml
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/di.xml
@@ -102,11 +102,6 @@
             <argument name="severity" xsi:type="string">S2</argument>
         </arguments>
     </type>
-    <type name="Magento\Checkout\Test\Constraint\AssertProductPresentInShoppingCart">
-        <arguments>
-            <argument name="severity" xsi:type="string">S2</argument>
-        </arguments>
-    </type>
     <type name="Magento\Checkout\Test\Constraint\AssertProductQtyInShoppingCart">
         <arguments>
             <argument name="severity" xsi:type="string">S2</argument>
@@ -157,4 +152,14 @@
             <argument name="severity" xsi:type="string">S2</argument>
         </arguments>
     </type>
+    <type name="Magento\Checkout\Test\Constraint\AssertCancelSuccessMessageInShoppingCart">
+        <arguments>
+            <argument name="severity" xsi:type="string">S1</argument>
+        </arguments>
+    </type>
+    <type name="Magento\Checkout\Test\Constraint\AssertProductPresentInShoppingCart">
+        <arguments>
+            <argument name="severity" xsi:type="string">S0</argument>
+        </arguments>
+    </type>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Edit/PageForm.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Edit/PageForm.php
index 9d7386380a09013b0a540df5bd4faf4d41a384b7..a46203cce370fdb89fc4fc103734e03928676e99 100644
--- a/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Edit/PageForm.php
+++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Edit/PageForm.php
@@ -28,6 +28,13 @@ class PageForm extends FormTabs
      */
     protected $contentForm = "#page_content";
 
+    /**
+     * Cms page loader.
+     *
+     * @var string
+     */
+    protected $loader = "data-role='loader'";
+
     /**
      * Page Content Show/Hide Editor toggle button.
      *
@@ -76,4 +83,19 @@ class PageForm extends FormTabs
         };
         return $this;
     }
+
+    /**
+     * Check if block with system variables is visible.
+     *
+     * @return bool
+     */
+    public function isVariablesBlockVisible()
+    {
+        $this->openTab('content');
+        /** @var \Magento\Cms\Test\Block\Adminhtml\Page\Edit\Tab\Content $contentTab */
+        $contentTab = $this->getTab('content');
+        $contentTab->clickInsertVariable();
+        $this->waitForElementNotVisible($this->loader);
+        return $contentTab->isVariablesBlockVisible();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Edit/Tab/Content.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Edit/Tab/Content.php
index a4f1bd4d1f85e2147472f21867d29f38bab437d0..0568d53b4580bdc34327c96e0c72ffe1a3ed3983 100644
--- a/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Edit/Tab/Content.php
+++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Edit/Tab/Content.php
@@ -171,4 +171,14 @@ class Content extends Tab
             'content_heading' => ''
         ];
     }
+
+    /**
+     * Check if system variables block is visible.
+     *
+     * @return bool
+     */
+    public function isVariablesBlockVisible()
+    {
+        return $this->_rootElement->find($this->systemVariableBlock, Locator::SELECTOR_XPATH)->isVisible();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Messages.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Messages.php
new file mode 100644
index 0000000000000000000000000000000000000000..1a3bbfefab7bae3eb38d7734347d13100a645fa5
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Messages.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Cms\Test\Block;
+
+/**
+ * Store front messages block.
+ */
+class Messages extends \Magento\Ui\Test\Block\Messages
+{
+    //
+}
diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.xml
index c4a98c9ba3223ee307df5cdce1aeb37e57d1304f..b747464c579dea402a631212419a0e01ff03598b 100644
--- a/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.xml
+++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.xml
@@ -11,11 +11,12 @@
         <block name="topmenu" class="Magento\Theme\Test\Block\Html\Topmenu" locator="[data-action='navigation']" strategy="css selector" />
         <block name="titleBlock" class="Magento\Theme\Test\Block\Html\Title" locator=".page-title-wrapper" strategy="css selector" />
         <block name="footerBlock" class="Magento\Theme\Test\Block\Html\Footer" locator="footer.page-footer" strategy="css selector" />
+        <block name="logoBlock" class="Magento\Theme\Test\Block\Html\Logo" locator=".header .logo" strategy="css selector" />
         <block name="linksBlock" class="Magento\Theme\Test\Block\Links" locator=".header .links" strategy="css selector" />
         <block name="storeSwitcherBlock" class="Magento\Store\Test\Block\Switcher" locator="[data-ui-id='language-switcher']" strategy="css selector" />
         <block name="currencyBlock" class="Magento\Directory\Test\Block\Currency\Switcher" locator=".switcher.currency" strategy="css selector" />
         <block name="cmsPageBlock" class="Magento\Cms\Test\Block\Page" locator=".page-main" strategy="css selector" />
         <block name="widgetView" class="Magento\Widget\Test\Block\WidgetView" locator=".widget" strategy="css selector" />
-        <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator=".messages" strategy="css selector"/>
+        <block name="messagesBlock" class="Magento\Cms\Test\Block\Messages" locator=".messages" strategy="css selector"/>
     </page>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Attribute.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Attribute.php
index 805f20d89640aa7b7df6a3f86a7df4dc2df61295..7b765d76e3e0773db79826274b4094acfba1ddc6 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Attribute.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Attribute.php
@@ -177,6 +177,7 @@ class Attribute extends Form
 
         //select attributes
         $this->getAttributesGrid()->resetFilter();
+        $this->getTemplateBlock()->waitLoader();
         $attributesList = $this->browser->find($this->selectedAttributes)->getText();
         if ($attributesList != '--') {
             $this->getAttributesGrid()->deselectAttributes();
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableProductsQtyAfterReorder.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableProductsQtyAfterReorder.php
new file mode 100644
index 0000000000000000000000000000000000000000..8ce9392b2d5878c29695e75e5fdd596f6d22dc78
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableProductsQtyAfterReorder.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\ConfigurableProduct\Test\Constraint;
+
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Sales\Test\Fixture\OrderInjectable;
+use Magento\Catalog\Test\Constraint\AssertProductForm;
+use Magento\Sales\Test\Constraint\AssertProductsQtyAfterOrderCancel;
+
+/**
+ * Assert that products quantity is correct after reorder.
+ */
+class AssertConfigurableProductsQtyAfterReorder extends AbstractConstraint
+{
+    /**
+     * Assert products quantity after placing new order with the same products.
+     *
+     * @param OrderInjectable $order
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductEdit $productPage
+     * @param FixtureFactory $fixtureFactory
+     * @param AssertProductForm $assertProductForm
+     * @param AssertConfigurableProductForm $assertConfigurableProductForm
+     * @param AssertProductsQtyAfterOrderCancel $assertProductsQty
+     * @return void
+     */
+    public function processAssert(
+        OrderInjectable $order,
+        CatalogProductIndex $productGrid,
+        CatalogProductEdit $productPage,
+        FixtureFactory $fixtureFactory,
+        AssertProductForm $assertProductForm,
+        AssertConfigurableProductForm $assertConfigurableProductForm,
+        AssertProductsQtyAfterOrderCancel $assertProductsQty
+    ) {
+        $newOrder = $fixtureFactory->createByCode('orderInjectable', [
+            'dataset' => 'default',
+            'data' => [
+                'entity_id' => [
+                    'products' => $order->getEntityId()['products'],
+                ]
+            ]
+        ]);
+        $newOrder->persist();
+        $assertProductsQty->processAssert(
+            $newOrder,
+            $productGrid,
+            $productPage,
+            $fixtureFactory,
+            $assertProductForm,
+            $assertConfigurableProductForm
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Products quantity is correct after reorder.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php
index 65715d116ab45780dcacae89ef987a16e9127ceb..6989e2785e96144c1f33c82fc495026dd56e5ccc 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php
@@ -129,7 +129,6 @@ class ConfigurableAttributesData extends DataSource
         foreach ($this->attributes as $attributeKey => $attribute) {
             $attributeData = $attribute->getData();
             $options = [];
-
             foreach ($attributeData['options'] as $key => $option) {
                 $options['option_key_' . $key] = $option;
             }
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct.xml
index 32f1957d4173f87b10069b60c8c428b921e260fb..b2a44d5454a9244c9b80102fc85aee6dcdaab986 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct.xml
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct.xml
@@ -39,6 +39,9 @@
             <field name="checkout_data" xsi:type="array">
                 <item name="dataset" xsi:type="string">configurable_default</item>
             </field>
+            <field name="category_ids" xsi:type="array">
+                <item name="dataset" xsi:type="string">default_subcategory</item>
+            </field>
         </dataset>
 
         <dataset name="out_of_stock">
@@ -334,6 +337,40 @@
             </field>
         </dataset>
 
+        <dataset name="with_one_option_buy_all">
+            <field name="name" xsi:type="string">Test configurable product %isolation%</field>
+            <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field>
+            <field name="product_has_weight" xsi:type="string">This item has weight</field>
+            <field name="weight" xsi:type="string">30</field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="url_key" xsi:type="string">configurable-product-%isolation%</field>
+            <field name="configurable_attributes_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">with_one_option_buy_all</item>
+            </field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">configurable_one_option</item>
+            </field>
+            <field name="price" xsi:type="array">
+                <item name="value" xsi:type="string">40</item>
+                <item name="dataset" xsi:type="string">price_40</item>
+            </field>
+        </dataset>
+
         <dataset name="with_out_of_stock_item">
             <field name="name" xsi:type="string">Test configurable product %isolation%</field>
             <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field>
@@ -497,5 +534,365 @@
                 <item name="dataset" xsi:type="string">price_40</item>
             </field>
         </dataset>
+
+        <dataset name="product_with_price_10">
+            <field name="name" xsi:type="string">Test configurable product %isolation%</field>
+            <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field>
+            <field name="price" xsi:type="array">
+                <item name="value" xsi:type="string">10</item>
+            </field>
+            <field name="special_price" xsi:type="string">10</field>
+            <field name="product_has_weight" xsi:type="string">This item has weight</field>
+            <field name="weight" xsi:type="string">5</field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="url_key" xsi:type="string">configurable-product-%isolation%</field>
+            <field name="configurable_attributes_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">two_options_with_assigned_product_special_price</item>
+            </field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">configurable_two_new_options_with_special_price</item>
+            </field>
+            <field name="category_ids" xsi:type="array">
+                <item name="dataset" xsi:type="string">default_subcategory</item>
+            </field>
+        </dataset>
+
+        <dataset name="first_product_with_custom_options_and_option_key_1">
+            <field name="name" xsi:type="string">Test configurable product %isolation%</field>
+            <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field>
+            <field name="special_price" xsi:type="string">49.99</field>
+            <field name="product_has_weight" xsi:type="string">This item has weight</field>
+            <field name="weight" xsi:type="string">5</field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="url_key" xsi:type="string">configurable-product-%isolation%</field>
+            <field name="configurable_attributes_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">two_options_with_assigned_product_special_price_2</item>
+            </field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="custom_options" xsi:type="array">
+                <item name="dataset" xsi:type="string">two_fixed_radio_options</item>
+            </field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">product_1_and_option_1</item>
+            </field>
+            <field name="category_ids" xsi:type="array">
+                <item name="dataset" xsi:type="string">default_subcategory</item>
+            </field>
+        </dataset>
+
+        <dataset name="first_product_with_custom_options_and_option_key_2">
+            <field name="name" xsi:type="string">Test configurable product %isolation%</field>
+            <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field>
+            <field name="special_price" xsi:type="string">10</field>
+            <field name="product_has_weight" xsi:type="string">This item has weight</field>
+            <field name="weight" xsi:type="string">5</field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="url_key" xsi:type="string">configurable-product-%isolation%</field>
+            <field name="configurable_attributes_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">two_options_with_assigned_product_special_price_2</item>
+            </field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="custom_options" xsi:type="array">
+                <item name="dataset" xsi:type="string">two_fixed_radio_options</item>
+            </field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">product_1_and_option_2</item>
+            </field>
+            <field name="category_ids" xsi:type="array">
+                <item name="dataset" xsi:type="string">default_subcategory</item>
+            </field>
+        </dataset>
+
+        <dataset name="second_product_with_custom_options_and_option_key_1">
+            <field name="name" xsi:type="string">Test configurable product %isolation%</field>
+            <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field>
+            <field name="special_price" xsi:type="string">10</field>
+            <field name="product_has_weight" xsi:type="string">This item has weight</field>
+            <field name="weight" xsi:type="string">5</field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="url_key" xsi:type="string">configurable-product-%isolation%</field>
+            <field name="configurable_attributes_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">two_options_with_assigned_product_special_price_2</item>
+            </field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="custom_options" xsi:type="array">
+                <item name="dataset" xsi:type="string">two_fixed_radio_options</item>
+            </field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">product_2_and_option_1</item>
+            </field>
+            <field name="category_ids" xsi:type="array">
+                <item name="dataset" xsi:type="string">default_subcategory</item>
+            </field>
+        </dataset>
+
+        <dataset name="second_product_with_custom_options_and_option_key_2">
+            <field name="name" xsi:type="string">Test configurable product %isolation%</field>
+            <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field>
+            <field name="special_price" xsi:type="string">10</field>
+            <field name="product_has_weight" xsi:type="string">This item has weight</field>
+            <field name="weight" xsi:type="string">5</field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="url_key" xsi:type="string">configurable-product-%isolation%</field>
+            <field name="configurable_attributes_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">two_options_with_assigned_product_special_price_2</item>
+            </field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="custom_options" xsi:type="array">
+                <item name="dataset" xsi:type="string">two_fixed_radio_options</item>
+            </field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">product_2_and_option_2</item>
+            </field>
+            <field name="category_ids" xsi:type="array">
+                <item name="dataset" xsi:type="string">default_subcategory</item>
+            </field>
+        </dataset>
+
+        <dataset name="Stellar_Solar_Jacket_SIZE_S">
+            <field name="name" xsi:type="string">Stellar Solar Jacket %isolation%</field>
+            <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field>
+            <field name="product_has_weight" xsi:type="string">This item has weight</field>
+            <field name="weight" xsi:type="string">5</field>
+            <field name="price" xsi:type="array">
+                <item name="value" xsi:type="string">75</item>
+                <item name="dataset" xsi:type="string">price_75</item>
+            </field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="url_key" xsi:type="string">configurable-product-%isolation%</field>
+            <field name="configurable_attributes_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">three_options_with_sizes_S_M_L</item>
+            </field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">custom_attribute_set_with_sizes</item>
+            </field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">configurable_the_first_option</item>
+            </field>
+            <field name="category_ids" xsi:type="array">
+                <item name="dataset" xsi:type="string">default_subcategory</item>
+            </field>
+        </dataset>
+
+        <dataset name="Stellar_Solar_Jacket_SIZE_M">
+            <field name="name" xsi:type="string">Stellar Solar Jacket %isolation%</field>
+            <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field>
+            <field name="product_has_weight" xsi:type="string">This item has weight</field>
+            <field name="weight" xsi:type="string">5</field>
+            <field name="price" xsi:type="array">
+                <item name="value" xsi:type="string">75</item>
+                <item name="dataset" xsi:type="string">price_75</item>
+            </field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="url_key" xsi:type="string">configurable-product-%isolation%</field>
+            <field name="configurable_attributes_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">three_options_with_sizes_S_M_L</item>
+            </field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">custom_attribute_set_with_sizes</item>
+            </field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">configurable_the_second_option</item>
+            </field>
+            <field name="category_ids" xsi:type="array">
+                <item name="dataset" xsi:type="string">default_subcategory</item>
+            </field>
+        </dataset>
+
+        <dataset name="Stellar_Solar_Jacket_SIZE_L">
+            <field name="name" xsi:type="string">Stellar Solar Jacket %isolation%</field>
+            <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field>
+            <field name="product_has_weight" xsi:type="string">This item has weight</field>
+            <field name="weight" xsi:type="string">5</field>
+            <field name="price" xsi:type="array">
+                <item name="value" xsi:type="string">75</item>
+                <item name="dataset" xsi:type="string">price_75</item>
+            </field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="url_key" xsi:type="string">configurable-product-%isolation%</field>
+            <field name="configurable_attributes_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">three_options_with_sizes_S_M_L</item>
+            </field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">custom_attribute_set_with_sizes</item>
+            </field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">configurable_the_third_option</item>
+            </field>
+            <field name="category_ids" xsi:type="array">
+                <item name="dataset" xsi:type="string">default_subcategory</item>
+            </field>
+        </dataset>
+
+        <dataset name="configurable_low_stock">
+            <field name="name" xsi:type="string">Test configurable product %isolation%</field>
+            <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field>
+            <field name="price" xsi:type="array">
+                <item name="value" xsi:type="string">40</item>
+                <item name="dataset" xsi:type="string">price_40</item>
+            </field>
+            <field name="product_has_weight" xsi:type="string">This item has weight</field>
+            <field name="weight" xsi:type="string">30</field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="url_key" xsi:type="string">configurable-product-%isolation%</field>
+            <field name="configurable_attributes_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">configurable_low_stock</item>
+            </field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">configurable_low_stock</item>
+            </field>
+        </dataset>
+
+        <dataset name="one_simple_product">
+            <field name="name" xsi:type="string">Test configurable product %isolation%</field>
+            <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field>
+            <field name="price" xsi:type="array">
+                <item name="value" xsi:type="string">560</item>
+            </field>
+            <field name="product_has_weight" xsi:type="string">This item has weight</field>
+            <field name="weight" xsi:type="string">2</field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="url_key" xsi:type="string">configurable-product-%isolation%</field>
+            <field name="configurable_attributes_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">one_option_with_simple_product</item>
+            </field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/CheckoutData.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/CheckoutData.xml
index 949c6dc065c494a18e2ae617ef859f6663dd05d4..9641bc980a71b6cbb1e24266f98b89b97fb80ff1 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/CheckoutData.xml
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/CheckoutData.xml
@@ -201,6 +201,42 @@
             </field>
         </dataset>
 
+        <dataset name="configurable_the_first_option">
+            <field name="options" xsi:type="array">
+                <item name="configurable_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_0</item>
+                    </item>
+                </item>
+            </field>
+            <field name="qty" xsi:type="string">1</field>
+        </dataset>
+
+        <dataset name="configurable_the_second_option">
+            <field name="options" xsi:type="array">
+                <item name="configurable_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_1</item>
+                    </item>
+                </item>
+            </field>
+            <field name="qty" xsi:type="string">1</field>
+        </dataset>
+
+        <dataset name="configurable_the_third_option">
+            <field name="options" xsi:type="array">
+                <item name="configurable_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_2</item>
+                    </item>
+                </item>
+            </field>
+            <field name="qty" xsi:type="string">1</field>
+        </dataset>
+
         <dataset name="configurable_two_options_with_fixed_price">
             <field name="options" xsi:type="array">
                 <item name="configurable_options" xsi:type="array">
@@ -227,5 +263,186 @@
                 <item name="price" xsi:type="string">11</item>
             </field>
         </dataset>
+
+        <dataset name="configurable_two_options_with_fixed_price_1">
+            <field name="options" xsi:type="array">
+                <item name="configurable_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_1</item>
+                    </item>
+                </item>
+            </field>
+            <field name="cartItem" xsi:type="array">
+                <item name="price" xsi:type="string">9</item>
+                <item name="qty" xsi:type="string">1</item>
+                <item name="subtotal" xsi:type="string">9</item>
+            </field>
+        </dataset>
+
+        <dataset name="product_1_and_option_1">
+            <field name="options" xsi:type="array">
+                <item name="configurable_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_0</item>
+                    </item>
+                </item>
+                <item name="custom_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_0</item>
+                    </item>
+                </item>
+            </field>
+            <field name="cartItem" xsi:type="array">
+                <item name="price" xsi:type="string">9</item>
+                <item name="qty" xsi:type="string">1</item>
+                <item name="subtotal" xsi:type="string">9</item>
+            </field>
+        </dataset>
+
+        <dataset name="product_1_and_option_2">
+            <field name="options" xsi:type="array">
+                <item name="configurable_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_0</item>
+                    </item>
+                </item>
+                <item name="custom_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_1</item>
+                    </item>
+                </item>
+            </field>
+            <field name="cartItem" xsi:type="array">
+                <item name="price" xsi:type="string">9</item>
+                <item name="qty" xsi:type="string">1</item>
+                <item name="subtotal" xsi:type="string">9</item>
+            </field>
+        </dataset>
+
+        <dataset name="product_2_and_option_1">
+            <field name="options" xsi:type="array">
+                <item name="configurable_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_1</item>
+                    </item>
+                </item>
+                <item name="custom_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_0</item>
+                    </item>
+                </item>
+            </field>
+            <field name="cartItem" xsi:type="array">
+                <item name="price" xsi:type="string">9</item>
+                <item name="qty" xsi:type="string">1</item>
+                <item name="subtotal" xsi:type="string">9</item>
+            </field>
+        </dataset>
+
+        <dataset name="product_2_and_option_2">
+            <field name="options" xsi:type="array">
+                <item name="configurable_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_1</item>
+                    </item>
+                </item>
+                <item name="custom_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_1</item>
+                    </item>
+                </item>
+            </field>
+            <field name="cartItem" xsi:type="array">
+                <item name="price" xsi:type="string">9</item>
+                <item name="qty" xsi:type="string">1</item>
+                <item name="subtotal" xsi:type="string">9</item>
+            </field>
+        </dataset>
+
+        <dataset name="configurable_option_1_and_custom_option_2">
+            <field name="options" xsi:type="array">
+                <item name="configurable_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_1</item>
+                    </item>
+                </item>
+                <item name="custom_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_1</item>
+                    </item>
+                </item>
+            </field>
+            <field name="cartItem" xsi:type="array">
+                <item name="qty" xsi:type="string">1</item>
+            </field>
+        </dataset>
+
+        <dataset name="configurable_option_2_and_custom_option_1">
+            <field name="options" xsi:type="array">
+                <item name="configurable_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_0</item>
+                    </item>
+                </item>
+                <item name="custom_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_0</item>
+                    </item>
+                </item>
+            </field>
+            <field name="cartItem" xsi:type="array">
+                <item name="qty" xsi:type="string">1</item>
+            </field>
+        </dataset>
+
+        <dataset name="configurable_option_2_and_custom_option_2">
+            <field name="options" xsi:type="array">
+                <item name="configurable_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_0</item>
+                    </item>
+                </item>
+                <item name="custom_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_1</item>
+                    </item>
+                </item>
+            </field>
+            <field name="cartItem" xsi:type="array">
+                <item name="qty" xsi:type="string">1</item>
+            </field>
+        </dataset>
+
+        <dataset name="configurable_low_stock">
+            <field name="options" xsi:type="array">
+                <item name="configurable_options" xsi:type="array">
+                    <item name="0" xsi:type="array">
+                        <item name="title" xsi:type="string">attribute_key_0</item>
+                        <item name="value" xsi:type="string">option_key_0</item>
+                    </item>
+                </item>
+            </field>
+            <field name="qty" xsi:type="string">1</field>
+            <field name="cartItem" xsi:type="array">
+                <item name="price" xsi:type="string">15</item>
+                <item name="qty" xsi:type="string">1</item>
+                <item name="subtotal" xsi:type="string">15</item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/ConfigurableAttributesData.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/ConfigurableAttributesData.xml
index 44e2e14545db02103bfe2fa2613f196937cfc558..dc3ffc389c56b1ac57b49b178536bafc25856829 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/ConfigurableAttributesData.xml
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/ConfigurableAttributesData.xml
@@ -440,6 +440,42 @@
             </field>
         </dataset>
 
+        <dataset name="two_options_with_assigned_product_special_price_2">
+            <field name="attributes_data" xsi:type="array">
+                <item name="attribute_key_0" xsi:type="array">
+                    <item name="options" xsi:type="array">
+                        <item name="option_key_0" xsi:type="array">
+                            <item name="label" xsi:type="string">option_key_1_%isolation%</item>
+                            <item name="pricing_value" xsi:type="string">79.99</item>
+                            <item name="include" xsi:type="string">Yes</item>
+                        </item>
+                        <item name="option_key_1" xsi:type="array">
+                            <item name="label" xsi:type="string">option_key_2_%isolation%</item>
+                            <item name="pricing_value" xsi:type="string">20.01</item>
+                            <item name="include" xsi:type="string">Yes</item>
+                        </item>
+                    </item>
+                </item>
+            </field>
+            <field name="attributes" xsi:type="array">
+                <item name="attribute_key_0" xsi:type="string">catalogProductAttribute::attribute_type_dropdown_two_options</item>
+            </field>
+            <field name="products" xsi:type="array">
+                <item name="attribute_key_0:option_key_0" xsi:type="string">catalogProductSimple::product_with_price_79_99</item>
+                <item name="attribute_key_0:option_key_1" xsi:type="string">catalogProductSimple::product_with_price_20_01</item>
+            </field>
+            <field name="matrix" xsi:type="array">
+                <item name="attribute_key_0:option_key_0" xsi:type="array">
+                    <item name="qty" xsi:type="string">10</item>
+                    <item name="weight" xsi:type="string">1</item>
+                </item>
+                <item name="attribute_key_0:option_key_1" xsi:type="array">
+                    <item name="qty" xsi:type="string">20</item>
+                    <item name="weight" xsi:type="string">1</item>
+                </item>
+            </field>
+        </dataset>
+
         <dataset name="two_options_with_assigned_product_tier_price">
             <field name="attributes_data" xsi:type="array">
                 <item name="attribute_key_0" xsi:type="array">
@@ -595,6 +631,44 @@
             </field>
         </dataset>
 
+        <dataset name="with_one_option_buy_all">
+            <field name="attributes_data" xsi:type="array">
+                <item name="attribute_key_0" xsi:type="array">
+                    <item name="options" xsi:type="array">
+                        <item name="option_key_0" xsi:type="array">
+                            <item name="pricing_value" xsi:type="string">1</item>
+                            <item name="include" xsi:type="string">Yes</item>
+                        </item>
+                        <item name="option_key_1" xsi:type="array">
+                            <item name="pricing_value" xsi:type="string">2</item>
+                            <item name="include" xsi:type="string">Yes</item>
+                        </item>
+                        <item name="option_key_2" xsi:type="array">
+                            <item name="pricing_value" xsi:type="string">3</item>
+                            <item name="include" xsi:type="string">Yes</item>
+                        </item>
+                    </item>
+                </item>
+            </field>
+            <field name="attributes" xsi:type="array">
+                <item name="attribute_key_0" xsi:type="string">catalogProductAttribute::attribute_type_dropdown</item>
+            </field>
+            <field name="matrix" xsi:type="array">
+                <item name="attribute_key_0:option_key_0" xsi:type="array">
+                    <item name="qty" xsi:type="string">1</item>
+                    <item name="weight" xsi:type="string">1</item>
+                </item>
+                <item name="attribute_key_0:option_key_1" xsi:type="array">
+                    <item name="qty" xsi:type="string">0</item>
+                    <item name="weight" xsi:type="string">1</item>
+                </item>
+                <item name="attribute_key_0:option_key_2" xsi:type="array">
+                    <item name="qty" xsi:type="string">0</item>
+                    <item name="weight" xsi:type="string">1</item>
+                </item>
+            </field>
+        </dataset>
+
         <dataset name="with_out_of_stock_item">
             <field name="attributes_data" xsi:type="array">
                 <item name="attribute_key_0" xsi:type="array">
@@ -612,6 +686,12 @@
             <field name="attributes" xsi:type="array">
                 <item name="attribute_key_0" xsi:type="string">catalogProductAttribute::attribute_type_dropdown_one_option</item>
             </field>
+            <field name="matrix" xsi:type="array">
+                <item name="attribute_key_0:option_key_0" xsi:type="array">
+                    <item name="qty" xsi:type="string">1</item>
+                    <item name="weight" xsi:type="string">1</item>
+                </item>
+            </field>
         </dataset>
 
         <dataset name="two_options_with_fixed_price">
@@ -713,5 +793,94 @@
                 </item>
             </field>
         </dataset>
+
+        <dataset name="three_options_with_sizes_S_M_L">
+            <field name="attributes_data" xsi:type="array">
+                <item name="attribute_key_0" xsi:type="array">
+                    <item name="options" xsi:type="array">
+                        <item name="option_key_0" xsi:type="array">
+                            <item name="label" xsi:type="string">SIZE_S</item>
+                            <item name="pricing_value" xsi:type="string">75</item>
+                            <item name="include" xsi:type="string">Yes</item>
+                        </item>
+                        <item name="option_key_1" xsi:type="array">
+                            <item name="label" xsi:type="string">SIZE_M</item>
+                            <item name="pricing_value" xsi:type="string">75</item>
+                            <item name="include" xsi:type="string">Yes</item>
+                        </item>
+                        <item name="option_key_2" xsi:type="array">
+                            <item name="label" xsi:type="string">SIZE_L</item>
+                            <item name="pricing_value" xsi:type="string">75</item>
+                            <item name="include" xsi:type="string">Yes</item>
+                        </item>
+                    </item>
+                </item>
+            </field>
+            <field name="attributes" xsi:type="array">
+                <item name="attribute_key_0" xsi:type="string">catalogProductAttribute::sizes_for_promo_rules</item>
+            </field>
+            <field name="matrix" xsi:type="array">
+                <item name="attribute_key_0:option_key_0" xsi:type="array">
+                    <item name="qty" xsi:type="string">10</item>
+                    <item name="weight" xsi:type="string">1</item>
+                </item>
+                <item name="attribute_key_0:option_key_1" xsi:type="array">
+                    <item name="qty" xsi:type="string">20</item>
+                    <item name="weight" xsi:type="string">1</item>
+                </item>
+                <item name="attribute_key_0:option_key_2" xsi:type="array">
+                    <item name="qty" xsi:type="string">20</item>
+                    <item name="weight" xsi:type="string">1</item>
+                </item>
+            </field>
+        </dataset>
+
+        <dataset name="configurable_low_stock">
+            <field name="attributes_data" xsi:type="array">
+                <item name="attribute_key_0" xsi:type="array">
+                    <item name="options" xsi:type="array">
+                        <item name="option_key_0" xsi:type="array">
+                            <item name="pricing_value" xsi:type="string">12.00</item>
+                            <item name="include" xsi:type="string">Yes</item>
+                        </item>
+                    </item>
+                </item>
+            </field>
+            <field name="attributes" xsi:type="array">
+                <item name="attribute_key_0" xsi:type="string">catalogProductAttribute::attribute_type_dropdown_one_option</item>
+            </field>
+            <field name="matrix" xsi:type="array">
+                <item name="attribute_key_0:option_key_0" xsi:type="array">
+                    <item name="qty" xsi:type="string">1</item>
+                    <item name="weight" xsi:type="string">1</item>
+                </item>
+            </field>
+        </dataset>
+
+        <dataset name="one_option_with_simple_product">
+            <field name="attributes_data" xsi:type="array">
+                <item name="attribute_key_0" xsi:type="array">
+                    <item name="options" xsi:type="array">
+                        <item name="option_key_0" xsi:type="array">
+                            <item name="label" xsi:type="string">option_key_1_%isolation%</item>
+                            <item name="pricing_value" xsi:type="string">560</item>
+                            <item name="include" xsi:type="string">Yes</item>
+                        </item>
+                    </item>
+                </item>
+            </field>
+            <field name="attributes" xsi:type="array">
+                <item name="attribute_key_0" xsi:type="string">catalogProductAttribute::attribute_type_dropdown_one_option</item>
+            </field>
+            <field name="products" xsi:type="array">
+                <item name="attribute_key_0:option_key_0" xsi:type="string">catalogProductSimple::default_with_weight_2</item>
+            </field>
+            <field name="matrix" xsi:type="array">
+                <item name="attribute_key_0:option_key_0" xsi:type="array">
+                    <item name="qty" xsi:type="string">10</item>
+                    <item name="weight" xsi:type="string">1</item>
+                </item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/Price.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/Price.xml
index 1b6282b9432c39fd444ca2089f1b8c8aa6bfb876..2704871a561d1dfc8102972b0fe558eb6f9e2da2 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/Price.xml
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/Price.xml
@@ -14,9 +14,17 @@
             <field name="category_price" xsi:type="string">40</field>
             <field name="compare_price" xsi:type="string">40</field>
         </dataset>
+        <dataset name="price_10">
+            <field name="category_price" xsi:type="string">10</field>
+            <field name="compare_price" xsi:type="string">10</field>
+        </dataset>
         <dataset name="MAGETWO-12620">
             <field name="category_price" xsi:type="string">11</field>
         </dataset>
+        <dataset name="price_75">
+            <field name="category_price" xsi:type="string">75</field>
+            <field name="compare_price" xsi:type="string">75</field>
+        </dataset>
         <dataset name="from-9">
             <field name="price_from" xsi:type="string">9</field>
         </dataset>
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCurrencyRateTest.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCurrencyRateTest.xml
index 6ba7729120ae909591f0703c36b83b51f2ea8aa0..a03f2aabd62399420d7a79d937e213c7944f7b65 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCurrencyRateTest.xml
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCurrencyRateTest.xml
@@ -7,7 +7,7 @@
  -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
     <testCase name="Magento\Directory\Test\TestCase\CreateCurrencyRateTest" summary="Create Currency Rate" ticketId="MAGETWO-36824">
-        <variation name="CreateCurrencyRateTestVariation3">
+        <variation name="CreateCurrencyRateTestVariation4">
             <data name="currencyRate/data/currency_from" xsi:type="string">USD</data>
             <data name="currencyRate/data/currency_to" xsi:type="string">UAH</data>
             <data name="currencyRate/data/rate" xsi:type="number">2.000</data>
diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml
index 77b311bd7a51f80b0347ba092dc700e467c2cf84..39853e7f8d8473b77b24cffd7028ca561124022b 100644
--- a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml
+++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml
@@ -211,5 +211,16 @@
                 </item>
             </field>
         </dataset>
+
+        <dataset name="config_allowed_currency_usd_and_uah">
+            <field name="currency/options/allow" xsi:type="array">
+                <item name="scope" xsi:type="string">currency</item>
+                <item name="scope_id" xsi:type="number">1</item>
+                <item name="value" xsi:type="array">
+                    <item name="US Dollar" xsi:type="string">USD</item>
+                    <item name="Ukrainian Hryvnia" xsi:type="string">UAH</item>
+                </item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/CurrencySymbolEntity.xml b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/CurrencySymbolEntity.xml
index 69db8d9ab8224d8c12737d0ea812d5a5758c2735..211ade81582531cd4f481037224e0207e0b53860 100644
--- a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/CurrencySymbolEntity.xml
+++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/CurrencySymbolEntity.xml
@@ -15,6 +15,7 @@
             <field name="custom_currency_symbol" xsi:type="array">
                 <item name="UAH" xsi:type="string">custom</item>
             </field>
+            <field name="code" xsi:type="string">UAH</field>
         </dataset>
 
         <dataset name="currency_symbols_eur">
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Account/AuthenticationPopup.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Account/AuthenticationPopup.php
index cc23998f60ac2ced653c294313cfa54eb98ef5a9..c796ed435b3bff9e9bf4676680bebaa9f9e5b1a1 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Account/AuthenticationPopup.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Account/AuthenticationPopup.php
@@ -32,7 +32,24 @@ class AuthenticationPopup extends Form
      *
      * @var string
      */
-    protected $createAccountButton = '.action.action-register.primary';
+    private $createAccountButton = '.action.action-register.primary';
+
+    /**
+     * Selector for password field with autocomplete off.
+     *
+     * @var string
+     */
+    private $passwordFieldWithAutocompleteOff = 'input[name="password"][autocomplete="off"]';
+
+    /**
+     * Checks if password field autocomplete is off.
+     *
+     * @return bool
+     */
+    public function isPasswordAutocompleteOff()
+    {
+        return $this->_rootElement->find($this->passwordFieldWithAutocompleteOff)->isVisible();
+    }
 
     /**
      * Click 'Create an Account' button.
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php
index e1e8f2ddebb709e17d8a977668f420d803247558..5980d0df9e3bc2f8b98ce79c92fb347c17bce44e 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php
@@ -38,6 +38,21 @@ class CustomerForm extends Form
      */
     protected $validationText = '.mage-error[for="%s"]';
 
+    /**
+     * Fixture mapping and fields revision.
+     *
+     * @param array|null $fields
+     * @param string|null $parent
+     * @return array
+     */
+    protected function dataMapping(array $fields = null, $parent = null)
+    {
+        if (isset($fields['website_id'])) {
+            unset($fields['website_id']);
+        }
+        return parent::dataMapping($fields, $parent);
+    }
+
     /**
      * Click on save button.
      *
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Login.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Login.php
index b28904aee9e070f38dc788598b21d139bee8d395..621d4be605120ccc51673c66cda35f80729914db 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Login.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Login.php
@@ -11,27 +11,43 @@ use Magento\Mtf\Client\Locator;
 use Magento\Mtf\Fixture\FixtureInterface;
 
 /**
- * Class Login
- * Form for frontend login
+ * Form for frontend login.
  */
 class Login extends Form
 {
     /**
-     * Login button for registered customers
+     * Login button for registered customers.
      *
      * @var string
      */
-    protected $loginButton = '.action.login';
+    private $loginButton = '.action.login';
 
     /**
-     * 'Register' customer button
+     * 'Register' customer button.
      *
      * @var string
      */
-    protected $registerButton = '.action.create';
+    private $registerButton = '.action.create';
 
     /**
-     * Login customer in the Frontend
+     * Selector for password field with autocomplete off.
+     *
+     * @var string
+     */
+    private $passwordFieldWithAutocompleteOff = 'input[name="login[password]"][autocomplete="off"]';
+
+    /**
+     * Checks if password field autocomplete is off.
+     *
+     * @return bool
+     */
+    public function isPasswordAutocompleteOff()
+    {
+        return $this->_rootElement->find($this->passwordFieldWithAutocompleteOff)->isVisible();
+    }
+
+    /**
+     * Login customer in the Frontend.
      *
      * @param FixtureInterface $customer
      *
@@ -45,7 +61,7 @@ class Login extends Form
     }
 
     /**
-     * Submit login form
+     * Submit login form.
      */
     public function submit()
     {
@@ -53,7 +69,7 @@ class Login extends Form
     }
 
     /**
-     * Press 'Register' button
+     * Press 'Register' button.
      */
     public function registerCustomer()
     {
@@ -61,7 +77,7 @@ class Login extends Form
     }
 
     /**
-     * Check whether block is visible
+     * Check whether block is visible.
      *
      * @return bool
      */
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Register.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Register.php
index 69be9bcd8cec8f5d3022075c74ab5f9a004afdf1..72ea1c185fd600a219739c2e7ae6aaf9ec648d26 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Register.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Register.php
@@ -44,6 +44,21 @@ class Register extends Form
      */
     protected $passwordConfirmationError = "#password-confirmation-error";
 
+    /**
+     * Fixture mapping.
+     *
+     * @param array|null $fields
+     * @param string|null $parent
+     * @return array
+     */
+    protected function dataMapping(array $fields = null, $parent = null)
+    {
+        if (isset($fields['website_id'])) {
+            unset($fields['website_id']);
+        }
+        return parent::dataMapping($fields, $parent);
+    }
+
     /**
      * Create new customer account and fill billing address if it exists
      *
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerLoginErrorMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerLoginErrorMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..155a1529cdb5e3e015828396672419330dc9b5dc
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerLoginErrorMessage.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Customer\Test\Constraint;
+
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Customer\Test\Page\CustomerAccountLogin;
+
+/**
+ * Assert that customer login error message is displayed.
+ */
+class AssertCustomerLoginErrorMessage extends AbstractConstraint
+{
+    /**
+     * Customer login error message.
+     */
+    const ERROR_MESSAGE = 'Invalid login or password.';
+
+    /**
+     * Assert that customer login error message is displayed.
+     *
+     * @param CustomerAccountLogin $customerLogin
+     * @return void
+     */
+    public function processAssert(
+        CustomerAccountLogin $customerLogin
+    ) {
+        \PHPUnit_Framework_Assert::assertEquals(
+            self::ERROR_MESSAGE,
+            $customerLogin->getMessages()->getErrorMessage(),
+            'Wrong error message is displayed.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Customer login error message is displayed.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerPasswordAutocompleteOnAuthorizationPopup.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerPasswordAutocompleteOnAuthorizationPopup.php
new file mode 100644
index 0000000000000000000000000000000000000000..95944eb3b47bd48cae99b615db1df9ba9c4d232c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerPasswordAutocompleteOnAuthorizationPopup.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Customer\Test\Constraint;
+
+use Magento\Checkout\Test\Page\CheckoutCart;
+use Magento\Checkout\Test\Page\CheckoutOnepage;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that autocomplete on password field on authorization pop up is off.
+ */
+class AssertCustomerPasswordAutocompleteOnAuthorizationPopup extends AbstractConstraint
+{
+    /**
+     * Assert that autocomplete on password field on authorization pop up is off.
+     *
+     * @param CheckoutOnepage $checkoutPage
+     * @param CheckoutCart $cartPage
+     * @return void
+     */
+    public function processAssert(
+        CheckoutOnepage $checkoutPage,
+        CheckoutCart $cartPage
+    ) {
+        $cartPage->open();
+        $cartPage->getProceedToCheckoutBlock()->proceedToCheckout();
+
+        \PHPUnit_Framework_Assert::assertTrue(
+            $checkoutPage->getAuthenticationPopupBlock()->isPasswordAutocompleteOff(),
+            'Password field autocomplete is not off.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Assert that autocomplete is off.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerPasswordAutocompleteOnSignIn.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerPasswordAutocompleteOnSignIn.php
new file mode 100644
index 0000000000000000000000000000000000000000..8794383a80c728e781a0b9ec3e5253c2d3eec21b
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerPasswordAutocompleteOnSignIn.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Customer\Test\Constraint;
+
+use Magento\Customer\Test\Page\CustomerAccountLogin;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that autocomplete on password field on sign in page is off.
+ */
+class AssertCustomerPasswordAutocompleteOnSignIn extends AbstractConstraint
+{
+    /**
+     * Assert that autocomplete on password field on sign in page is off.
+     *
+     * @param CustomerAccountLogin $loginPage
+     * @return void
+     */
+    public function processAssert(CustomerAccountLogin $loginPage)
+    {
+        $loginPage->open();
+        \PHPUnit_Framework_Assert::assertTrue(
+            $loginPage->getLoginBlock()->isPasswordAutocompleteOff(),
+            'Password field autocomplete is not off.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Assert that autocomplete is off.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertMassActionSuccessUpdateMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertMassActionSuccessUpdateMessage.php
index ae044ca025d1347112fe09cb0fe1323062cf8b81..d2637b6c8ea29ee4177593a5ddcb7031a7773461 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertMassActionSuccessUpdateMessage.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertMassActionSuccessUpdateMessage.php
@@ -28,13 +28,12 @@ class AssertMassActionSuccessUpdateMessage extends AbstractConstraint
     /**
      * Assert update message is appears on customer grid (Customers > All Customers)
      *
-     * @param Customer|Customer[] $customer
+     * @param Customer[] $customers
      * @param CustomerIndex $pageCustomerIndex
      * @return void
      */
-    public function processAssert($customer, CustomerIndex $pageCustomerIndex)
+    public function processAssert(array $customers, CustomerIndex $pageCustomerIndex)
     {
-        $customers = is_array($customer) ? $customer : [$customer];
         $actualMessage = $pageCustomerIndex->getMessagesBlock()->getSuccessMessage();
         \PHPUnit_Framework_Assert::assertEquals(sprintf(self::UPDATE_MESSAGE, count($customers)), $actualMessage);
     }
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Customer.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Customer.xml
index 3a09f8861b601f7d1ba6a58b72b454a66cc78fa6..8572b15420ff8a381a01ac7d61a87d89af6f7949 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Customer.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Customer.xml
@@ -37,7 +37,7 @@
         <field name="store_id" is_required="1" group="account_information" />
         <field name="suffix" is_required="0" group="account_information" />
         <field name="taxvat" is_required="0" group="account_information" />
-        <field name="website_id" is_required="1" group="account_information" />
+        <field name="website_id" is_required="1" group="account_information" source="Magento\Customer\Test\Fixture\Customer\WebsiteId" />
         <field name="amount_delta" is_required="1" group="store_credit" />
         <field name="is_subscribed" />
         <field name="password" group="null" />
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Customer/WebsiteId.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Customer/WebsiteId.php
new file mode 100644
index 0000000000000000000000000000000000000000..18daa3271d8faf980f4146af3d24fb8d853571dc
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Customer/WebsiteId.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Customer\Test\Fixture\Customer;
+
+use Magento\Mtf\Fixture\DataSource;
+use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Store\Test\Fixture\Store;
+use Magento\Store\Test\Fixture\Website;
+
+/**
+ * Prepare website.
+ */
+class WebsiteId extends DataSource
+{
+    /**
+     * Store Fixture.
+     *
+     * @var Store
+     */
+    private $store;
+
+    /**
+     * Website.
+     *
+     * @var Website
+     */
+    private $website;
+
+    /**
+     * Fixture Factory instance.
+     *
+     * @var FixtureFactory
+     */
+    private $fixtureFactory;
+
+    /**
+     * Rought fixture field data.
+     *
+     * @var array
+     */
+    private $fixtureData = null;
+
+    /**
+     * @constructor
+     * @param FixtureFactory $fixtureFactory
+     * @param array $params
+     * @param array $data
+     */
+    public function __construct(
+        FixtureFactory $fixtureFactory,
+        array $params,
+        $data = []
+    ) {
+        $this->fixtureFactory = $fixtureFactory;
+        $this->params = $params;
+        $this->fixtureData = $data;
+    }
+
+    /**
+     * Return prepared data set.
+     *
+     * @param string $key [optional]
+     * @return mixed
+     * @throws \Exception
+     */
+    public function getData($key = null)
+    {
+        if (empty($this->fixtureData)) {
+            throw new \Exception("Data must be set");
+        }
+
+        if (isset($this->fixtureData['website'])) {
+            $this->website = $this->fixtureData['website'];
+            $this->data = $this->fixtureData['website']->getName();
+        } else {
+            if (isset($this->fixtureData['dataset'])) {
+                $store = $this->fixtureFactory->createByCode('store', $this->fixtureData);
+
+                if (!$store->getStoreId()) {
+                    $store->persist();
+                }
+
+                $website = $store->getDataFieldConfig('group_id')['source']
+                    ->getStoreGroup()->getDataFieldConfig('website_id')['source']->getWebsite();
+
+                $this->data = $website->getName();
+                $this->website = $website;
+                $this->store = $store;
+            }
+        }
+
+        return parent::getData($key);
+    }
+
+    /**
+     * Return store.
+     *
+     * @return Store
+     */
+    public function getStore()
+    {
+        return $this->store;
+    }
+
+    /**
+     * Return website code.
+     *
+     * @return Website
+     */
+    public function getWebsite()
+    {
+        return $this->website;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php
index f880983074576396646ed0dc10be2ebb12c6b708..546f58cb6cb04fc4e59c8582a55e2818d32756ad 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php
@@ -87,6 +87,7 @@ class Curl extends AbstractCurl implements CustomerInterface
         /** @var Customer $customer */
         $data = $customer->getData();
         $data['group_id'] = $this->getCustomerGroup($customer);
+        $data['website_id'] = $this->getCustomerWebsite($customer);
         $address = [];
         $url = $_ENV['app_frontend_url'] . 'customer/account/createpost/?nocookie=true';
 
@@ -229,4 +230,15 @@ class Curl extends AbstractCurl implements CustomerInterface
 
         return $curlData;
     }
+
+    /**
+     * Prepare customer website data.
+     *
+     * @param Customer $customer
+     * @return int
+     */
+    private function getCustomerWebsite(Customer $customer)
+    {
+        return $customer->getDataFieldConfig('website_id')['source']->getWebsite()->getWebsiteId();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Webapi.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Webapi.php
index aa63bfa50f052096d0468b5df6e8c12e7c1075af..a223985872434fc2bde5c906cc4d6b0fe8bd00b8 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Webapi.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Webapi.php
@@ -79,6 +79,7 @@ class Webapi extends AbstractWebapi implements CustomerInterface
         $data['customer'] = $this->replaceMappingData($customer->getData());
         $data['customer']['group_id'] = $this->getCustomerGroup($customer);
         $data['password'] = $data['customer']['password'];
+        $data['customer']['website_id'] = $this->getCustomerWebsite($customer);
         unset($data['customer']['password']);
         unset($data['customer']['password_confirmation']);
         $data = $this->prepareAddressData($data);
@@ -182,4 +183,15 @@ class Webapi extends AbstractWebapi implements CustomerInterface
 
         return $addressData;
     }
+
+    /**
+     * Prepare customer website data.
+     *
+     * @param Customer $customer
+     * @return int
+     */
+    private function getCustomerWebsite(Customer $customer)
+    {
+        return $customer->getDataFieldConfig('website_id')['source']->getWebsite()->getWebsiteId();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.xml
index 2edc328b5c5df40df321e66a34fa1ee7c6d4e835..6e7e76524557dd6ec875af966ef23e85bef6a73c 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.xml
@@ -297,5 +297,17 @@
             <field name="region_id" xsi:type="string">California</field>
             <field name="postcode" xsi:type="string">90230</field>
         </dataset>
+
+        <dataset name="AVS_street_does_not_match_address">
+            <field name="firstname" xsi:type="string">John</field>
+            <field name="lastname" xsi:type="string">Doe</field>
+            <field name="company" xsi:type="string">Magento %isolation%</field>
+            <field name="city" xsi:type="string">Culver City</field>
+            <field name="street" xsi:type="string">49354 Main</field>
+            <field name="telephone" xsi:type="string">555-55-555-55</field>
+            <field name="country_id" xsi:type="string">United States</field>
+            <field name="region_id" xsi:type="string">California</field>
+            <field name="postcode" xsi:type="string">90230</field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/ConfigData.xml
index 524805f44038143d426624c563afefe1054ffd6f..eee9dbeb74a6d4f76d7d5746fa56702df1ab789f 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/ConfigData.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/ConfigData.xml
@@ -60,5 +60,14 @@
                 <item name="value" xsi:type="string">0</item>
             </field>
         </dataset>
+
+        <dataset name="password_autocomplete_off">
+            <field name="customer/password/autocomplete_on_storefront" xsi:type="array">
+                <item name="scope" xsi:type="string">customer</item>
+                <item name="scope_id" xsi:type="number">1</item>
+                <item name="label" xsi:type="string">No</item>
+                <item name="value" xsi:type="string">0</item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Customer.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Customer.xml
index 3be7447c91dad863564835d08b459b6addfd86f5..eba62cba79ce2ff7ef1488863a6c666f49c8aaad 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Customer.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Customer.xml
@@ -16,6 +16,9 @@
             <field name="email" xsi:type="string">JohnDoe_%isolation%@example.com</field>
             <field name="password" xsi:type="string">123123^q</field>
             <field name="password_confirmation" xsi:type="string">123123^q</field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
 
         <dataset name="customer_with_new_customer_group">
@@ -27,6 +30,9 @@
             <field name="email" xsi:type="string">JohnDoe_%isolation%@example.com</field>
             <field name="password" xsi:type="string">123123^q</field>
             <field name="password_confirmation" xsi:type="string">123123^q</field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
 
         <dataset name="johndoe">
@@ -40,6 +46,9 @@
             <field name="group_id" xsi:type="array">
                 <item name="dataset" xsi:type="string">General</item>
             </field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
 
         <dataset name="johndoe_retailer">
@@ -53,13 +62,18 @@
             <field name="password_confirmation" xsi:type="string">123123^q</field>
             <field name="dob" xsi:type="string">01/01/1990</field>
             <field name="gender" xsi:type="string">Male</field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
 
         <dataset name="defaultBackend">
-            <field name="website_id" xsi:type="string">Main Website</field>
             <field name="firstname" xsi:type="string">John</field>
             <field name="lastname" xsi:type="string">Doe</field>
             <field name="email" xsi:type="string">JohnDoe_%isolation%@example.com</field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
 
         <dataset name="johndoe_with_addresses">
@@ -74,6 +88,9 @@
             <field name="address" xsi:type="array">
                 <item name="dataset" xsi:type="string">US_address</item>
             </field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
 
         <dataset name="johndoe_unique">
@@ -88,6 +105,9 @@
             <field name="address" xsi:type="array">
                 <item name="dataset" xsi:type="string">US_address_NY</item>
             </field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
 
         <dataset name="johndoe_unique_TX">
@@ -102,6 +122,9 @@
             <field name="address" xsi:type="array">
                 <item name="dataset" xsi:type="string">US_address_TX</item>
             </field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
 
         <dataset name="johndoe_with_multiple_addresses">
@@ -116,6 +139,9 @@
             <field name="address" xsi:type="array">
                 <item name="dataset" xsi:type="string">US_address_NY, US_address</item>
             </field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
 
         <dataset name="register_customer">
@@ -138,6 +164,9 @@
             <field name="address" xsi:type="array">
                 <item name="dataset" xsi:type="string">US_address_1</item>
             </field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
 
         <dataset name="backend_retailer_customer">
@@ -152,6 +181,9 @@
             <field name="address" xsi:type="array">
                 <item name="dataset" xsi:type="string">US_address_1</item>
             </field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
 
         <dataset name="customer_US">
@@ -163,6 +195,9 @@
             <field name="address" xsi:type="array">
                 <item name="dataset" xsi:type="string">US_address_1</item>
             </field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
 
         <dataset name="customer_UK_1_default_billing_address">
@@ -174,6 +209,9 @@
             <field name="address" xsi:type="array">
                 <item name="dataset" xsi:type="string">UK_address_default_billing</item>
             </field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
 
         <dataset name="customer_UK_address_with_VAT">
@@ -185,6 +223,9 @@
             <field name="address" xsi:type="array">
                 <item name="dataset" xsi:type="string">UK_address_with_VAT</item>
             </field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
 
         <dataset name="customer_UK_US_addresses">
@@ -196,6 +237,9 @@
             <field name="address" xsi:type="array">
                 <item name="dataset" xsi:type="string">UK_address_default_billing, US_address_default_shipping</item>
             </field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
 
         <dataset name="customer_US_DE_UK">
@@ -210,6 +254,39 @@
             <field name="address" xsi:type="array">
                 <item name="dataset" xsi:type="string">US_address, DE_address, UK_address</item>
             </field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+        </dataset>
+
+        <dataset name="default_in_custom_website">
+            <field name="firstname" xsi:type="string">John</field>
+            <field name="lastname" xsi:type="string">Doe</field>
+            <field name="group_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">General</item>
+            </field>
+            <field name="email" xsi:type="string">JohnDoe_%isolation%@example.com</field>
+            <field name="password" xsi:type="string">123123^q</field>
+            <field name="password_confirmation" xsi:type="string">123123^q</field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">custom_store</item>
+            </field>
+        </dataset>
+
+        <dataset name="johndoe_wholesale">
+            <field name="firstname" xsi:type="string">John</field>
+            <field name="lastname" xsi:type="string">Doe</field>
+            <field name="group_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">Wholesale</item>
+            </field>
+            <field name="email" xsi:type="string">JohnDoe_%isolation%@example.com</field>
+            <field name="password" xsi:type="string">123123^q</field>
+            <field name="password_confirmation" xsi:type="string">123123^q</field>
+            <field name="dob" xsi:type="string">01/01/1990</field>
+            <field name="gender" xsi:type="string">Male</field>
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
         </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateExistingCustomerFrontendEntity.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateExistingCustomerFrontendEntity.xml
index 34479021cf93590c8e10c1b371afadb4d9de16d3..324b47bfebb82e2aa736b6baaef37d45dbc4264e 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateExistingCustomerFrontendEntity.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateExistingCustomerFrontendEntity.xml
@@ -13,6 +13,7 @@
             <data name="customer/data/email" xsi:type="string">johndoe%isolation%@example.com</data>
             <data name="customer/data/password" xsi:type="string">123123q#</data>
             <data name="customer/data/password_confirmation" xsi:type="string">123123q#</data>
+            <data name="customer/data/website_id/dataset" xsi:type="string">default</data>
             <constraint name="Magento\Customer\Test\Constraint\AssertCustomerFailRegisterMessage" />
         </variation>
     </testCase>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/LoginOnFrontendFailTest.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/LoginOnFrontendFailTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e5929458ce653cba1b58b1f4f336e303f056e2f7
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/LoginOnFrontendFailTest.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Customer\Test\TestCase;
+
+use Magento\Customer\Test\Page\CustomerAccountLogin;
+use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Mtf\TestCase\Injectable;
+use Magento\Customer\Test\Fixture\Customer;
+
+/**
+ * Precondition:
+ * 1. Customer is created.
+ *
+ * Steps:
+ * 1. Open login page.
+ * 2. Fill email.
+ * 3. Fill wrong password.
+ * 4. Click login.
+ * 5. Check error message.
+ *
+ * @group Customer
+ * @ZephyrId MAGETWO-16883
+ */
+class LoginOnFrontendFailTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    /* end tags */
+
+    /**
+     * Login on frontend.
+     *
+     * @param Customer $customer
+     * @param CustomerAccountLogin $loginPage
+     * @param FixtureFactory $fixtureFactory
+     * @return void
+     */
+    public function test(Customer $customer, CustomerAccountLogin $loginPage, FixtureFactory $fixtureFactory)
+    {
+        // Precondition
+        $customer->persist();
+        $customerData = $customer->getData();
+        $customerData['password'] = 'fail';
+        $customerData['group_id'] = ['dataset' => 'default'];
+        $failCustomer = $fixtureFactory->createByCode('customer', ['data' => $customerData]);
+
+        // Steps
+        $loginPage->open();
+        $loginPage->getLoginBlock()->fill($failCustomer);
+        $loginPage->getLoginBlock()->submit();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/LoginOnFrontendFailTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/LoginOnFrontendFailTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3d2a6cec11acce8beed4af3d3a98bec65b9cc09e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/LoginOnFrontendFailTest.xml
@@ -0,0 +1,15 @@
+<?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\Customer\Test\TestCase\LoginOnFrontendFailTest" summary="Check error message with wrong credentials" ticketId="MAGETWO-16883">
+        <variation name="LoginOnFrontendFailTestVariation1">
+            <data name="customer/dataset" xsi:type="string">default</data>
+            <constraint name="Magento\Customer\Test\Constraint\AssertCustomerLoginErrorMessage" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/MassAssignCustomerGroupTest.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/MassAssignCustomerGroupTest.php
index f7448024b93aa2d889a4ac35b31df900adb68aed..d3c2cefcbd511e96ede91e33620a9cce1bd4ebb2 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/MassAssignCustomerGroupTest.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/MassAssignCustomerGroupTest.php
@@ -7,8 +7,8 @@
 namespace Magento\Customer\Test\TestCase;
 
 use Magento\Customer\Test\Fixture\CustomerGroup;
-use Magento\Customer\Test\Fixture\Customer;
 use Magento\Customer\Test\Page\Adminhtml\CustomerIndex;
+use Magento\Mtf\Fixture\FixtureFactory;
 use Magento\Mtf\TestCase\Injectable;
 
 /**
@@ -17,7 +17,7 @@ use Magento\Mtf\TestCase\Injectable;
  * Test Flow:
  *
  * Preconditions:
- * 1. Create customer
+ * 1. Create customers
  * 2. Create customer group
  *
  * Steps:
@@ -30,7 +30,7 @@ use Magento\Mtf\TestCase\Injectable;
  * 7. Perform all assertions
  *
  * @group Customer_Groups, Customers
- * @ZephyrId MAGETWO-27892
+ * @ZephyrId MAGETWO-27892, MAGETWO-19456
  */
 class MassAssignCustomerGroupTest extends Injectable
 {
@@ -53,19 +53,6 @@ class MassAssignCustomerGroupTest extends Injectable
      */
     protected $customersGridActions = 'Assign a Customer Group';
 
-    /**
-     * Prepare data
-     *
-     * @param Customer $customer
-     * @return array
-     */
-    public function __prepare(Customer $customer)
-    {
-        $customer->persist();
-
-        return ['customer' => $customer];
-    }
-
     /**
      * Injection data
      *
@@ -80,19 +67,32 @@ class MassAssignCustomerGroupTest extends Injectable
     /**
      * Mass assign customer group
      *
-     * @param Customer $customer
      * @param CustomerGroup $customerGroup
-     * @return void
+     * @param FixtureFactory $fixtureFactory
+     * @param array $customers
+     * @return array
      */
-    public function test(Customer $customer, CustomerGroup $customerGroup)
+    public function test(CustomerGroup $customerGroup, FixtureFactory $fixtureFactory, array $customers)
     {
+        // Preconditions
+        if (!$customerGroup->hasData('customer_group_id')) {
+            $customerGroup->persist();
+        }
+
+        $customerEmails = [];
+        foreach ($customers as &$customer) {
+            $customer = $fixtureFactory->createByCode('customer', ['dataset' => $customer]);
+            $customer->persist();
+            $customerEmails[] = ['email' => $customer->getEmail()];
+        }
+
         // Steps
-        $customerGroup->persist();
         $this->customerIndex->open();
         $this->customerIndex->getCustomerGridBlock()->massaction(
-            [['email' => $customer->getEmail()]],
+            $customerEmails,
             [$this->customersGridActions => $customerGroup->getCustomerGroupCode()],
             true
         );
+        return ['customers' => $customers];
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/MassAssignCustomerGroupTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/MassAssignCustomerGroupTest.xml
index af57affcd7f07bf42182f444b16fc85ffe274ade..464fed37d5df12ffbc6e7c49bb1087dbea87b27a 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/MassAssignCustomerGroupTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/MassAssignCustomerGroupTest.xml
@@ -7,11 +7,21 @@
  -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
     <testCase name="Magento\Customer\Test\TestCase\MassAssignCustomerGroupTest" summary="Mass Assign Customer's Group to Customers" ticketId="MAGETWO-27892">
-        <variation name="MassAssignCustomerGroupTestVariation1">
-            <data name="tag" xsi:type="string">test_type:extended_acceptance_test, to_maintain:yes</data>
+        <variation name="MassAssignCustomerGroupTestVariation1" summary="Customer is created and mass action for changing customer group to created group is applied">
+            <data name="customers" xsi:type="array">
+                <item name="0" xsi:type="string">default</item>
+            </data>
             <data name="customerGroup/dataset" xsi:type="string">default</data>
             <constraint name="Magento\Customer\Test\Constraint\AssertMassActionSuccessUpdateMessage" />
             <constraint name="Magento\Customer\Test\Constraint\AssertCustomerGroupInGrid" />
         </variation>
+        <variation name="MassAssignCustomerGroupTestVariation2" summary="Two customers are created and mass actions for changing customer group to 'Retail' is applied" ticketId="MAGETWO-19456">
+            <data name="customers" xsi:type="array">
+                <item name="0" xsi:type="string">default</item>
+                <item name="1" xsi:type="string">customer_US</item>
+            </data>
+            <data name="customerGroup/dataset" xsi:type="string">Retailer</data>
+            <constraint name="Magento\Customer\Test\Constraint\AssertMassActionSuccessUpdateMessage" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/PasswordAutocompleteOffTest.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/PasswordAutocompleteOffTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..347fda1e91ff17e06755ba159c5e71d7ad85fb92
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/PasswordAutocompleteOffTest.php
@@ -0,0 +1,88 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Customer\Test\TestCase;
+
+use Magento\Catalog\Test\Fixture\CatalogProductSimple;
+use Magento\Catalog\Test\Page\Product\CatalogProductView;
+use Magento\Checkout\Test\Page\CheckoutCart;
+use Magento\Mtf\Client\BrowserInterface;
+use Magento\Mtf\TestCase\Injectable;
+
+/**
+ * Precondition:
+ * 1. Configs are applied.
+ * 2. Simple product is created.
+ *
+ * Steps:
+ * 1. Add product to shopping cart.
+ * 2. Perform asserts.
+ *
+ * @group Customer
+ * @ZephyrId MAGETWO-45324
+ */
+class PasswordAutocompleteOffTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    /* end tags */
+
+    /**
+     * Configuration setting.
+     *
+     * @var string
+     */
+    protected $configData;
+
+    /**
+     * Test password field autocomplete is off.
+     *
+     * @param BrowserInterface $browser
+     * @param CatalogProductView $catalogProductView
+     * @param CheckoutCart $checkoutCart
+     * @param CatalogProductSimple $product
+     * @param string $configData
+     * @return void
+     */
+    public function test(
+        BrowserInterface $browser,
+        CatalogProductView $catalogProductView,
+        CheckoutCart $checkoutCart,
+        CatalogProductSimple $product,
+        $configData
+    ) {
+        $this->configData = $configData;
+
+        // Preconditions
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData]
+        )->run();
+
+        $product->persist();
+
+        // Steps
+        $checkoutCart->open();
+        $checkoutCart->getCartBlock()->clearShoppingCart();
+
+        $browser->open($_ENV['app_frontend_url'] . $product->getUrlKey() . '.html');
+        $catalogProductView->getViewBlock()->addToCart($product);
+        $catalogProductView->getMessagesBlock()->waitSuccessMessage();
+    }
+
+    /**
+     * Clean data after running test.
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData, 'rollback' => true]
+        )->run();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/PasswordAutocompleteOffTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/PasswordAutocompleteOffTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ee5a591fb449998fb1f9c0518dd79c0d9e32acf4
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/PasswordAutocompleteOffTest.xml
@@ -0,0 +1,17 @@
+<?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\Customer\Test\TestCase\PasswordAutocompleteOffTest" summary="Test that autocomplete is off" ticketId="MAGETWO-45324">
+        <variation name="RegisterCustomerFrontendEntityTestVariation1" summary="Test that autocomplete is off">
+            <data name="product/dataset" xsi:type="string">default</data>
+            <data name="configData" xsi:type="string">disable_guest_checkout,password_autocomplete_off</data>
+            <constraint name="Magento\Customer\Test\Constraint\AssertCustomerPasswordAutocompleteOnAuthorizationPopup" />
+            <constraint name="Magento\Customer\Test\Constraint\AssertCustomerPasswordAutocompleteOnSignIn" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/etc/testcase.xml
index d34a96100f74e9b087ed3415e21a571dadb5ca44..4ecd82ac96da37315ed387968d7ed1eff01d83b0 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/etc/testcase.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/etc/testcase.xml
@@ -10,7 +10,8 @@
     <step name="createCustomer" module="Magento_Customer" next="openCustomerOnBackend"/>
     <step name="openCustomerOnBackend" module="Magento_Customer" next="createOrderFromCustomerAccount"/>
     <step name="createOrderFromCustomerAccount" module="Magento_Customer" next="createProducts"/>
-    <step name="createProducts" module="Magento_Catalog" next="addProducts"/>
+    <step name="createProducts" module="Magento_Catalog" next="selectStore"/>
+    <step name="selectStore" module="Magento_Sales" next="addProducts" />
     <step name="addProducts" module="Magento_Sales" next="updateProductsData"/>
     <step name="updateProductsData" module="Magento_Sales" next="fillBillingAddress"/>
     <step name="fillBillingAddress" module="Magento_Sales" next="fillShippingAddress"/>
diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertShippingPriceWithCustomCurrency.php b/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertShippingPriceWithCustomCurrency.php
new file mode 100644
index 0000000000000000000000000000000000000000..a2e3de1d933d9cd9200777ce17cd7ad2ffc7e128
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertShippingPriceWithCustomCurrency.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Directory\Test\Constraint;
+
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Cms\Test\Page\CmsIndex;
+use Magento\Checkout\Test\Page\CheckoutOnepage;
+use Magento\Mtf\TestStep\TestStepFactory;
+use Magento\Catalog\Test\Fixture\CatalogProductSimple;
+use Magento\CurrencySymbol\Test\Fixture\CurrencySymbolEntity;
+
+/**
+ * Assert that shipping amount is correct in not base currency.
+ */
+class AssertShippingPriceWithCustomCurrency extends AbstractConstraint
+{
+    /**
+     * Assert that shipping amount is correct in not base currency in the checkout page.
+     *
+     * @param CmsIndex $cmsIndex
+     * @param CheckoutOnepage $checkoutOnepage
+     * @param TestStepFactory $testStepFactory
+     * @param CatalogProductSimple $product
+     * @param CurrencySymbolEntity $currencySymbol
+     * @param string $shippingAmount
+     * @param array $shipping
+     * @return void
+     */
+    public function processAssert(
+        CmsIndex $cmsIndex,
+        CheckoutOnepage $checkoutOnepage,
+        TestStepFactory $testStepFactory,
+        CatalogProductSimple $product,
+        CurrencySymbolEntity $currencySymbol,
+        $shippingAmount,
+        array $shipping
+    ) {
+        $cmsIndex->open();
+        $cmsIndex->getLinksBlock()->waitWelcomeMessage();
+        $cmsIndex->getCurrencyBlock()->switchCurrency($currencySymbol);
+        $testStepFactory->create(
+            \Magento\Checkout\Test\TestStep\AddProductsToTheCartStep::class,
+            ['products' => [$product]]
+        )->run();
+        $testStepFactory->create(\Magento\Checkout\Test\TestStep\ProceedToCheckoutStep::class)->run();
+        \PHPUnit_Framework_Assert::assertEquals(
+            $shippingAmount,
+            $checkoutOnepage->getShippingMethodBlock()->getShippingMethodAmount($shipping),
+            'Shipping amount is not correct in the checkout page.'
+        );
+    }
+
+    /**
+     * Returns a string representation of successful assertion.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Shipping amount is correct in the checkout page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.xml b/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.xml
index e984cad9ca327aa2a0896e44fc85e365e9f24503..a491a74aca727636d8015f4e7731a7ceac7765c1 100644
--- a/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Directory/Test/TestCase/CreateCurrencyRateTest.xml
@@ -33,5 +33,18 @@
             <constraint name="Magento\Directory\Test\Constraint\AssertCurrencyRateSuccessSaveMessage" />
             <constraint name="Magento\Directory\Test\Constraint\AssertCurrencyRateAppliedOnProductPage" />
         </variation>
+        <variation name="CreateCurrencyRateTestVariation3" summary="Create currency rate if is not base currency" ticketId="MAGETWO-45310">
+            <data name="currencyRate/data/currency_from" xsi:type="string">USD</data>
+            <data name="currencyRate/data/currency_to" xsi:type="string">UAH</data>
+            <data name="currencyRate/data/rate" xsi:type="number">0.5</data>
+            <data name="currencySymbol/dataset" xsi:type="string">currency_symbols_uah</data>
+            <data name="product" xsi:type="string">catalogProductSimple::simple_10_dollar</data>
+            <data name="shippingAmount" xsi:type="string">â‚´2.50</data>
+            <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data>
+            <data name="shipping/shipping_method" xsi:type="string">Fixed</data>
+            <data name="config/dataset" xsi:type="string">config_allowed_currency_usd_and_uah</data>
+            <constraint name="Magento\Directory\Test\Constraint\AssertCurrencyRateSuccessSaveMessage" />
+            <constraint name="Magento\Directory\Test\Constraint\AssertShippingPriceWithCustomCurrency" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Repository/DownloadableProduct.xml b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Repository/DownloadableProduct.xml
index c304fe8079b5618055f6976b80e0369be9c9ca82..90b0d9196c8dffb4daf727beb11a727834d18e4b 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Repository/DownloadableProduct.xml
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Repository/DownloadableProduct.xml
@@ -194,5 +194,34 @@
                 <item name="dataset" xsi:type="string">downloadable_one_dollar_product_with_no_separated_link</item>
             </field>
         </dataset>
+
+        <dataset name="with_two_separately_links_buy_all">
+            <field name="name" xsi:type="string">Downloadable product %isolation%</field>
+            <field name="sku" xsi:type="string">downloadable_product_%isolation%</field>
+            <field name="url_key" xsi:type="string">downloadable-product-%isolation%</field>
+            <field name="price" xsi:type="array">
+                <item name="value" xsi:type="string">20</item>
+            </field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="qty" xsi:type="string">1</item>
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</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="downloadable_links" xsi:type="array">
+                <item name="dataset" xsi:type="string">with_two_separately_links</item>
+            </field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">downloadable_with_two_separately_links</item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml
index 7f1fd69d8e784d08363b07837c35e9ec30c54ea0..7522226ee804549079637e15f41b369899fec84e 100644
--- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml
@@ -38,6 +38,59 @@
             </field>
         </dataset>
 
+        <dataset name="withSimpleProduct">
+            <field name="name" xsi:type="string">Test grouped product %isolation%</field>
+            <field name="sku" xsi:type="string">sku_test_grouped_product_%isolation%</field>
+            <field name="category_ids" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="associated" xsi:type="array">
+                <item name="dataset" xsi:type="string">one_simple_product</item>
+            </field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="url_key" xsi:type="string">test-grouped-product-%isolation%</field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+        </dataset>
+
+        <dataset name="withSimpleProduct_without_category">
+            <field name="name" xsi:type="string">Test grouped product %isolation%</field>
+            <field name="sku" xsi:type="string">sku_test_grouped_product_%isolation%</field>
+            <field name="associated" xsi:type="array">
+                <item name="dataset" xsi:type="string">one_simple_product</item>
+            </field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="url_key" xsi:type="string">test-grouped-product-%isolation%</field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+        </dataset>
+
         <dataset name="grouped_product_out_of_stock">
             <field name="name" xsi:type="string">Test grouped product %isolation%</field>
             <field name="sku" xsi:type="string">sku_test_grouped_product_%isolation%</field>
@@ -129,6 +182,37 @@
             </field>
         </dataset>
 
+        <dataset name="three_simple_products_buy_all">
+            <field name="name" xsi:type="string">Grouped product %isolation%</field>
+            <field name="sku" xsi:type="string">grouped_product_%isolation%</field>
+            <field name="category_ids" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="associated" xsi:type="array">
+                <item name="dataset" xsi:type="string">three_simple_products_buy_all</item>
+            </field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="url_key" xsi:type="string">test-grouped-product-%isolation%</field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">grouped_three_simple_products</item>
+            </field>
+        </dataset>
+
         <dataset name="grouped_product_with_special_price">
             <field name="name" xsi:type="string">Test grouped product with special price %isolation%</field>
             <field name="sku" xsi:type="string">sku_test_grouped_product_with_special_price_%isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct/Associated.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct/Associated.xml
index 2360e0547c8c81bfdb0fe1cd4142ead581575ea9..519165a97ec757ac37b93a71c0c32a56da6a85bf 100644
--- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct/Associated.xml
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct/Associated.xml
@@ -28,6 +28,20 @@
             </field>
         </dataset>
 
+        <dataset name="one_simple_product">
+            <field name="assigned_products" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="id" xsi:type="string">%id%</item>
+                    <item name="name" xsi:type="string">%item1_simple::getProductName%</item>
+                    <item name="position" xsi:type="string">%position%</item>
+                    <item name="qty" xsi:type="string">1</item>
+                </item>
+            </field>
+            <field name="products" xsi:type="array">
+                <item name="0" xsi:type="string">catalogProductSimple::default</item>
+            </field>
+        </dataset>
+
         <dataset name="defaultSimpleProduct_without_qty">
             <field name="assigned_products" xsi:type="array">
                 <item name="0" xsi:type="array">
@@ -119,6 +133,34 @@
             </field>
         </dataset>
 
+        <dataset name="three_simple_products_buy_all">
+            <field name="assigned_products" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="id" xsi:type="string">%id%</item>
+                    <item name="name" xsi:type="string">%item1_simple::getProductName%</item>
+                    <item name="position" xsi:type="string">%position%</item>
+                    <item name="qty" xsi:type="string">3</item>
+                </item>
+                <item name="1" xsi:type="array">
+                    <item name="id" xsi:type="string">%id%</item>
+                    <item name="name" xsi:type="string">%item1_simple::getProductName%</item>
+                    <item name="position" xsi:type="string">%position%</item>
+                    <item name="qty" xsi:type="string">1</item>
+                </item>
+                <item name="2" xsi:type="array">
+                    <item name="id" xsi:type="string">%id%</item>
+                    <item name="name" xsi:type="string">%item1_simple::getProductName%</item>
+                    <item name="position" xsi:type="string">%position%</item>
+                    <item name="qty" xsi:type="string">2</item>
+                </item>
+            </field>
+            <field name="products" xsi:type="array">
+                <item name="0" xsi:type="string">catalogProductSimple::default_qty_3</item>
+                <item name="1" xsi:type="string">catalogProductSimple::default_qty_1</item>
+                <item name="2" xsi:type="string">catalogProductSimple::default_qty_2</item>
+            </field>
+        </dataset>
+
         <dataset name="simple_downloadable_virtual">
             <field name="assigned_products" xsi:type="array">
                 <item name="0" xsi:type="array">
diff --git a/dev/tests/functional/tests/app/Magento/Indexer/Test/Block/Adminhtml/IndexManagement/Grid.php b/dev/tests/functional/tests/app/Magento/Indexer/Test/Block/Adminhtml/IndexManagement/Grid.php
new file mode 100644
index 0000000000000000000000000000000000000000..64642a5b37012b3fc8d609853d433d11b869d83a
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Indexer/Test/Block/Adminhtml/IndexManagement/Grid.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Indexer\Test\Block\Adminhtml\IndexManagement;
+
+use Magento\Mtf\Client\Locator;
+use Magento\Backend\Test\Block\Widget\Grid as WidgetGrid;
+
+/**
+ * Grid in Index Management Page.
+ */
+class Grid extends WidgetGrid
+{
+    /**
+     * Select action toggle.
+     *
+     * @var string
+     */
+    private $selectAction = './/*[@id=\'gridIndexer_massaction-select\']/option[.=\'Update by Schedule\']';
+
+    /**
+     * Select Submit Button.
+     *
+     * @var string
+     */
+    private $updateButton = './/button[@title=\'Submit\']';
+
+    /**
+     * Indexer Status locator.
+     *
+     * @var string
+     */
+    private $indxerStatus = './/*[@data-column=\'indexer_status\']/span/span';
+
+    /**
+     * Filters array mapping.
+     *
+     * @var array
+     */
+    protected $filters = [
+        'Indexer' => [
+            'selector' => '[name="indexer_ids"]',
+            'input' => 'checkbox',
+            'value' => 'Yes',
+        ],
+    ];
+
+    /**
+     * Update indexers action in Index Management Page.
+     *
+     * @param array $indexers
+     * @throws \Exception
+     * @return void
+     */
+    public function updateBySchedule(array $indexers)
+    {
+        foreach ($indexers as $indexer) {
+            $selectItem = $this->getRow(['Indexer' => trim($indexer)])->find($this->selectItem);
+            if ($selectItem->isVisible()) {
+                $selectItem->click();
+            } else {
+                throw new \Exception("Searched item was not found by filter\n" . print_r($indexer, true));
+            }
+        }
+        $this->_rootElement->find($this->selectAction, Locator::SELECTOR_XPATH, 'select')->click();
+        $this->_rootElement->find($this->updateButton, Locator::SELECTOR_XPATH)->click();
+    }
+
+    /**
+     * Return indexers status in Index Management Page.
+     *
+     * @param string $indexer
+     * @return string|array
+     */
+    public function getIndexerStatus($indexer)
+    {
+        return $this->getRow(['Indexer' => trim($indexer)])
+            ->find($this->indxerStatus, Locator::SELECTOR_XPATH)->getText();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Indexer/Test/Constraint/AssertIndexerStatus.php b/dev/tests/functional/tests/app/Magento/Indexer/Test/Constraint/AssertIndexerStatus.php
new file mode 100644
index 0000000000000000000000000000000000000000..38e45ed3cd68ebf8538f1e07a060a9a288ef8925
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Indexer/Test/Constraint/AssertIndexerStatus.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Indexer\Test\Constraint;
+
+use Magento\Indexer\Test\Page\Adminhtml\IndexManagement;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert Indexer status in Index Management Page.
+ */
+class AssertIndexerStatus extends AbstractConstraint
+{
+    /**
+     * Indexer status in Index Management Page.
+     *
+     * @var array
+     */
+    private $indexerStatus = [
+        0 => 'REINDEX REQUIRED',
+        1 => 'READY'
+    ];
+
+    /**
+     * Assert Correct Indexer Status.
+     *
+     * @param IndexManagement $indexManagement
+     * @param array $indexers
+     * @param bool $expectedStatus
+     * @return void
+     */
+    public function processAssert(IndexManagement $indexManagement, array $indexers, bool $expectedStatus = true)
+    {
+        $expectedStatus = $expectedStatus === false ? $this->indexerStatus[0] : $this->indexerStatus[1];
+        $indexManagement->open();
+        foreach ($indexers as $indexer) {
+            $indexerStatus = $indexManagement->getMainBlock()->getIndexerStatus($indexer);
+            \PHPUnit_Framework_Assert::assertEquals(
+                $expectedStatus,
+                $indexerStatus,
+                'Wrong ' . $indexer . ' status is displayed.'
+                . "\nExpected: " . $expectedStatus
+                . "\nActual: " . $indexerStatus
+            );
+        }
+    }
+
+    /**
+     * Returns indexers status.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Indexer status is correct.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Indexer/Test/Constraint/AssertUpdateByScheduleSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Indexer/Test/Constraint/AssertUpdateByScheduleSuccessSaveMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..13f40ac38dcc09629b1efe1b157cb7a2b809cf95
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Indexer/Test/Constraint/AssertUpdateByScheduleSuccessSaveMessage.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Indexer\Test\Constraint;
+
+use Magento\Indexer\Test\Page\Adminhtml\IndexManagement;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert indexers status after change action.
+ */
+class AssertUpdateByScheduleSuccessSaveMessage extends AbstractConstraint
+{
+    /**
+     * Text of save success message.
+     */
+    const SUCCESS_SAVE_MESSAGE = '%s indexer(s) are in "Update by Schedule" mode.';
+
+    /**
+     * Assert attribute Update by Schedule.
+     *
+     * @param IndexManagement $indexManagement
+     * @param array $indexers
+     * @return void
+     */
+    public function processAssert(IndexManagement $indexManagement, array $indexers)
+    {
+        $actualMessage = $indexManagement->getMessagesBlock()->getSuccessMessage();
+        \PHPUnit_Framework_Assert::assertEquals(
+            sprintf(self::SUCCESS_SAVE_MESSAGE, count($indexers)),
+            $actualMessage,
+            'Wrong success message is displayed.'
+            . "\nExpected: " . sprintf(self::SUCCESS_SAVE_MESSAGE, count($indexers))
+            . "\nActual: " . $actualMessage
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Attribute Update by Schedule message is present.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Indexer/Test/Page/Adminhtml/IndexManagement.xml b/dev/tests/functional/tests/app/Magento/Indexer/Test/Page/Adminhtml/IndexManagement.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b955ed5548b457592b75728c5aeaa79bcbd8fae9
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Indexer/Test/Page/Adminhtml/IndexManagement.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/pages.xsd">
+    <page name="IndexManagement" area="Adminhtml" mca="indexer/indexer/list" module="Magento_Indexer">
+        <block name="mainBlock" class="Magento\Indexer\Test\Block\Adminhtml\IndexManagement\Grid" locator="#anchor-content" strategy="css selector" />
+        <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator=".messages .message" strategy="css selector" />
+    </page>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/PageCache/Test/Constraint/AssertCacheStatus.php b/dev/tests/functional/tests/app/Magento/PageCache/Test/Constraint/AssertCacheStatus.php
index 22adf03401c77b8fb7663ad6a234f4141cd3cb79..f5809f8b9d855dc404ea239f7cad81467efc0d09 100644
--- a/dev/tests/functional/tests/app/Magento/PageCache/Test/Constraint/AssertCacheStatus.php
+++ b/dev/tests/functional/tests/app/Magento/PageCache/Test/Constraint/AssertCacheStatus.php
@@ -21,6 +21,7 @@ class AssertCacheStatus extends AbstractConstraint
      */
     private $cacheTypes = [
         'block_html' => "Blocks HTML output",
+        'full_page' => "Page Cache",
     ];
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/PageCache/Test/Constraint/AssertCategoryCaching.php b/dev/tests/functional/tests/app/Magento/PageCache/Test/Constraint/AssertCategoryCaching.php
new file mode 100644
index 0000000000000000000000000000000000000000..7c6e5fcca61256500eba7b208038df7f5e7a01e5
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/PageCache/Test/Constraint/AssertCategoryCaching.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\PageCache\Test\Constraint;
+
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Fixture\Category;
+use Magento\Catalog\Test\Constraint\AssertProductNotVisibleInCategory;
+use Magento\Catalog\Test\Constraint\AssertProductInCategory;
+use Magento\Catalog\Test\Page\Category\CatalogCategoryView;
+use Magento\Cms\Test\Page\CmsIndex;
+use Magento\Mtf\Util\Command\Cli\Cron;
+
+/**
+ * Assert that category products are visible after indexing.
+ */
+class AssertCategoryCaching extends AbstractConstraint
+{
+    /**
+     * Assert category products are displayed only after indexing.
+     *
+     * @param Category $category
+     * @param CatalogCategoryView $categoryView
+     * @param CmsIndex $cmsIndex
+     * @param AssertProductInCategory $assertProduct
+     * @param AssertProductNotVisibleInCategory $assertProductNotVisible
+     * @param Cron $cron
+     * @return void
+     */
+    public function processAssert(
+        Category $category,
+        CatalogCategoryView $categoryView,
+        CmsIndex $cmsIndex,
+        AssertProductInCategory $assertProduct,
+        AssertProductNotVisibleInCategory $assertProductNotVisible,
+        Cron $cron
+    ) {
+        $products = $category->getDataFieldConfig('category_products')['source']->getProducts();
+        foreach ($products as $product) {
+            $assertProductNotVisible->processAssert($categoryView, $cmsIndex, $product, $category);
+        }
+
+        $cron->run();
+        $cron->run();
+
+        foreach ($products as $product) {
+            $assertProduct->processAssert($categoryView, $cmsIndex, $product, $category);
+        }
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Category products are visible after indexing.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/PageCache/Test/TestCase/CacheStatusOnScheduledIndexingTest.php b/dev/tests/functional/tests/app/Magento/PageCache/Test/TestCase/CacheStatusOnScheduledIndexingTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e4aa022667021a9f893ea901c2c9916ffce027b2
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/PageCache/Test/TestCase/CacheStatusOnScheduledIndexingTest.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\PageCache\Test\TestCase;
+
+use Magento\Mtf\TestCase\Injectable;
+use Magento\Indexer\Test\Page\Adminhtml\IndexManagement;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogCategoryEdit;
+use Magento\Catalog\Test\Fixture\Category;
+use Magento\Mtf\Client\BrowserInterface;
+use Magento\Mtf\Util\Command\Cli\Cache;
+use Magento\Mtf\Fixture\FixtureFactory;
+
+/**
+ * Steps:
+ * 1. Set all indexers to Update on Schedule mode.
+ * 2. Clear all caches.
+ * 3. Create a category.
+ * 4. Add some products to the category.
+ * 5. Perform asserts.
+ *
+ * @ZephyrId MAGETWO-45833
+ */
+class CacheStatusOnScheduledIndexingTest extends Injectable
+{
+    /* tags */
+    const MVP = 'no';
+    /* end tags */
+
+    /**
+     * Index Management page.
+     *
+     * @var IndexManagement
+     */
+    private $indexManagement;
+
+    /**
+     * Category Edit page.
+     *
+     * @var CatalogCategoryEdit
+     */
+    private $categoryEdit;
+
+    /**
+     * Browser instance.
+     *
+     * @var BrowserInterface
+     */
+    private $browser;
+
+    /**
+     * Fixture factory.
+     *
+     * @var FixtureFactory
+     */
+    private $fixtureFactory;
+
+    /**
+     * Cli command to do operations with cache.
+     *
+     * @var Cache
+     */
+    private $cache;
+
+    /**
+     * Inject pages.
+     *
+     * @param IndexManagement $indexManagement
+     * @param CatalogCategoryEdit $categoryEdit
+     * @param BrowserInterface $browser
+     * @param FixtureFactory $fixtureFactory
+     * @param Cache $cache
+     * @return void
+     */
+    public function __inject(
+        IndexManagement $indexManagement,
+        CatalogCategoryEdit $categoryEdit,
+        BrowserInterface $browser,
+        FixtureFactory $fixtureFactory,
+        Cache $cache
+    ) {
+        $this->indexManagement = $indexManagement;
+        $this->categoryEdit = $categoryEdit;
+        $this->browser = $browser;
+        $this->fixtureFactory = $fixtureFactory;
+        $this->cache = $cache;
+    }
+
+    /**
+     * Create category with products and verify cache invalidation.
+     *
+     * @param Category $initialCategory
+     * @param Category $category
+     * @return array
+     */
+    public function test(Category $initialCategory, Category $category)
+    {
+        $this->indexManagement->open();
+        $this->indexManagement->getMainBlock()->massaction([], 'Update by Schedule', false, 'Select All');
+        $initialCategory->persist();
+        $this->cache->flush();
+
+        $this->browser->open($_ENV['app_frontend_url'] . $initialCategory->getUrlKey() . '.html');
+        $this->categoryEdit->open(['id' => $initialCategory->getId()]);
+        $this->categoryEdit->getEditForm()->fill($category);
+        $this->categoryEdit->getFormPageActions()->save();
+
+        $products = $category->getDataFieldConfig('category_products')['source']->getProducts();
+        return [
+            'category' => $this->fixtureFactory->createByCode(
+                'category',
+                [
+                    'data' => array_merge(
+                        $initialCategory->getData(),
+                        $category->getData(),
+                        ['category_products' => ['products' => $products]]
+                    )
+                ]
+            ),
+        ];
+    }
+
+    /**
+     * Restore indexers mode.
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        $this->indexManagement->open();
+        $this->indexManagement->getMainBlock()->massaction([], 'Update on Save', false, 'Select All');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/PageCache/Test/TestCase/CacheStatusOnScheduledIndexingTest.xml b/dev/tests/functional/tests/app/Magento/PageCache/Test/TestCase/CacheStatusOnScheduledIndexingTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9f16518ae61764d2bee702e8d394b3a9f50e58ca
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/PageCache/Test/TestCase/CacheStatusOnScheduledIndexingTest.xml
@@ -0,0 +1,18 @@
+<?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\PageCache\Test\TestCase\CacheStatusOnScheduledIndexingTest" summary="Page cache invalidation and flushing on scheduled indexing" ticketId="MAGETWO-45833">
+        <variation name="CacheStatusOnScheduledIndexingTestVariation1" summary="Verify page cache invalidation and flushing on scheduled indexing" ticketId="MAGETWO-45833">
+            <data name="initialCategory/dataset" xsi:type="string">default</data>
+            <data name="category/data/category_products/dataset" xsi:type="string">catalogProductSimple::default,catalogProductSimple::product_20_dollar</data>
+            <data name="caches/full_page" xsi:type="string">Enabled</data>
+            <constraint name="Magento\PageCache\Test\Constraint\AssertCategoryCaching" />
+            <constraint name="Magento\PageCache\Test\Constraint\AssertCacheStatus" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/Repository/ConfigData.xml
index 1669352dc026ef02c295fce1153f63e3beabf225..f1d041f0a5b344fb76e91acd57124eb03d9f6ae8 100644
--- a/dev/tests/functional/tests/app/Magento/Paypal/Test/Repository/ConfigData.xml
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Repository/ConfigData.xml
@@ -25,54 +25,54 @@
         </dataset>
 
         <dataset name="paypal_direct">
-            <field name="payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/business_account" xsi:type="array">
+            <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/paypal_payflow_api_settings/business_account" xsi:type="array">
                 <item name="scope" xsi:type="string">payment</item>
                 <item name="scope_id" xsi:type="number">1</item>
-                <item name="label" xsi:type="string">Yes</item>
-                <item name="value" xsi:type="string">PAYPAL_BUSINESS_ACCOUNT</item>
+                <item name="label" xsi:type="string">Email Associated with PayPal Merchant Account (Optional)</item>
+                <item name="value" xsi:type="string">%payflow_pro_business_account%</item>
             </field>
-            <field name="payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/api_username" xsi:type="array">
+            <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/paypal_payflow_api_settings/partner" xsi:type="array">
                 <item name="scope" xsi:type="string">payment</item>
                 <item name="scope_id" xsi:type="number">1</item>
-                <item name="label" xsi:type="string"/>
-                <item name="value" xsi:type="string">PAYPAL_API_USERNAME</item>
+                <item name="label" xsi:type="string">Partner</item>
+                <item name="value" xsi:type="string">%payflow_pro_partner%</item>
             </field>
-            <field name="payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/api_password" xsi:type="array">
+            <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/paypal_payflow_api_settings/user" xsi:type="array">
                 <item name="scope" xsi:type="string">payment</item>
                 <item name="scope_id" xsi:type="number">1</item>
-                <item name="label" xsi:type="string"/>
-                <item name="value" xsi:type="string">PAYPAL_API_PASSWORD</item>
+                <item name="label" xsi:type="string">User</item>
+                <item name="value" xsi:type="string">%payflow_pro_user%</item>
             </field>
-            <field name="payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/api_signature" xsi:type="array">
+            <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/paypal_payflow_api_settings/vendor" xsi:type="array">
                 <item name="scope" xsi:type="string">payment</item>
                 <item name="scope_id" xsi:type="number">1</item>
-                <item name="label" xsi:type="string"/>
-                <item name="value" xsi:type="string">PAYPAL_API_SIGNATURE</item>
+                <item name="label" xsi:type="string">Vendor</item>
+                <item name="value" xsi:type="string">%payflow_pro_vendor%</item>
             </field>
-            <field name="payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/sandbox_flag" xsi:type="array">
+            <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/paypal_payflow_api_settings/pwd" xsi:type="array">
                 <item name="scope" xsi:type="string">payment</item>
                 <item name="scope_id" xsi:type="number">1</item>
-                <item name="label" xsi:type="string">Yes</item>
-                <item name="value" xsi:type="number">1</item>
+                <item name="label" xsi:type="string">Password</item>
+                <item name="value" xsi:type="string">%payflow_pro_pwd%</item>
             </field>
-            <field name="payment/paypal_direct/debug" xsi:type="array">
+            <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/paypal_payflow_api_settings/sandbox_flag" xsi:type="array">
                 <item name="scope" xsi:type="string">payment</item>
                 <item name="scope_id" xsi:type="number">1</item>
-                <item name="label" xsi:type="string">Yes</item>
+                <item name="label" xsi:type="string">Test Mode</item>
                 <item name="value" xsi:type="number">1</item>
             </field>
-            <field name="payment/paypal_direct/active" xsi:type="array">
+            <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/enable_paypal_payflow" xsi:type="array">
                 <item name="scope" xsi:type="string">payment</item>
                 <item name="scope_id" xsi:type="number">1</item>
-                <item name="label" xsi:type="string">Yes</item>
+                <item name="label" xsi:type="string">Enable this Solution</item>
                 <item name="value" xsi:type="number">1</item>
             </field>
         </dataset>
         <dataset name="paypal_direct_rollback">
-            <field name="payment/paypal_direct/active" xsi:type="array">
+            <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/enable_paypal_payflow" xsi:type="array">
                 <item name="scope" xsi:type="string">payment</item>
                 <item name="scope_id" xsi:type="number">1</item>
-                <item name="label" xsi:type="string">Yes</item>
+                <item name="label" xsi:type="string">Enable this Solution</item>
                 <item name="value" xsi:type="number">0</item>
             </field>
         </dataset>
@@ -219,6 +219,23 @@
             </field>
         </dataset>
 
+        <dataset name="payflowpro_avs_street_does_not_match">
+            <field name="payment/payflowpro/avs_street" xsi:type="array">
+                <item name="scope" xsi:type="string">payment</item>
+                <item name="scope_id" xsi:type="number">1</item>
+                <item name="label" xsi:type="string">Yes</item>
+                <item name="value" xsi:type="number">1</item>
+            </field>
+        </dataset>
+        <dataset name="payflowpro_avs_street_does_not_match_rollback">
+            <field name="payment/payflowpro/avs_street" xsi:type="array">
+                <item name="scope" xsi:type="string">payment</item>
+                <item name="scope_id" xsi:type="number">1</item>
+                <item name="label" xsi:type="string">No</item>
+                <item name="value" xsi:type="number">0</item>
+            </field>
+        </dataset>
+
         <dataset name="hosted_pro">
             <field name="payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/business_account" xsi:type="array">
                 <item name="scope" xsi:type="string">payment</item>
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CloseOrderTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CloseOrderTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..30385e1cd2006c5dd86f98a8f4da1a9d032c6efd
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CloseOrderTest.xml
@@ -0,0 +1,57 @@
+<?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\Sales\Test\TestCase\CloseOrderTest" summary="Close order">
+        <variation name="CloseOrderTestWithPayPalPaymentsPro" summary="Close order with PayPal Payments Pro" ticketId="MAGETWO-13015">
+            <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data>
+            <data name="customer/dataset" xsi:type="string">default</data>
+            <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data>
+            <data name="checkoutMethod" xsi:type="string">guest</data>
+            <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data>
+            <data name="shipping/shipping_method" xsi:type="string">Fixed</data>
+            <data name="payment/method" xsi:type="string">payflowpro</data>
+            <data name="prices" xsi:type="array">
+                <item name="grandTotal" xsi:type="string">15.00</item>
+            </data>
+            <data name="capturedPrices" xsi:type="array">
+                <item name="0" xsi:type="string">15.00</item>
+            </data>
+            <data name="creditCard/dataset" xsi:type="string">visa_default</data>
+            <data name="status" xsi:type="string">Complete</data>
+            <data name="configData" xsi:type="string">paypal_direct</data>
+            <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data>
+            <constraint name="Magento\Sales\Test\Constraint\AssertCaptureInCommentsHistory" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceItems" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" />
+        </variation>
+        <variation name="CloseOrderTestWithPayPalPayflowPro" summary="Close order with PayPal Payflow Pro" ticketId="MAGETWO-13020">
+            <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data>
+            <data name="customer/dataset" xsi:type="string">default</data>
+            <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data>
+            <data name="checkoutMethod" xsi:type="string">guest</data>
+            <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data>
+            <data name="shipping/shipping_method" xsi:type="string">Fixed</data>
+            <data name="payment/method" xsi:type="string">payflowpro</data>
+            <data name="order/data/price/dataset" xsi:type="string">full_invoice_with_product_10_dollar</data>
+            <data name="prices" xsi:type="array">
+                <item name="grandTotal" xsi:type="string">15.00</item>
+            </data>
+            <data name="capturedPrices" xsi:type="array">
+                <item name="0" xsi:type="string">15.00</item>
+            </data>
+            <data name="creditCard/dataset" xsi:type="string">visa_default</data>
+            <data name="status" xsi:type="string">Complete</data>
+            <data name="configData" xsi:type="string">payflowpro, payflowpro_use_vault</data>
+            <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data>
+            <constraint name="Magento\Sales\Test\Constraint\AssertCaptureInCommentsHistory" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceItems" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceInInvoicesTab" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" />
+        </variation>
+    </testCase>
+</config>
\ No newline at end of file
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateOnlineCreditMemoTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateOnlineCreditMemoTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f859f579ecea45c5c992017a09df061b11b70bbc
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateOnlineCreditMemoTest.xml
@@ -0,0 +1,42 @@
+<?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\Sales\Test\TestCase\CreateOnlineCreditMemoTest" summary="Create online credit memo for order placed with online payment method">
+        <variation name="CreateCreditMemoPaymentsProTestVariation1" summary="Create Refund for Order Paid with PayPal Payments Pro" ticketId="MAGETWO-13059">
+            <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data>
+            <data name="customer/dataset" xsi:type="string">default</data>
+            <data name="checkoutMethod" xsi:type="string">guest</data>
+            <data name="refundedPrices" xsi:type="array">
+                <item name="0" xsi:type="string">15.00</item>
+            </data>
+            <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data>
+            <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data>
+            <data name="shipping/shipping_method" xsi:type="string">Fixed</data>
+            <data name="payment/method" xsi:type="string">payflowpro</data>
+            <data name="configData" xsi:type="string">paypal_direct</data>
+            <data name="creditCard/dataset" xsi:type="string">visa_default</data>
+            <data name="data/items_data/0/qty" xsi:type="string">-</data>
+            <data name="data/form_data/do_shipment" xsi:type="string">Yes</data>
+            <data name="status" xsi:type="string">Closed</data>
+            <data name="transactions/Refund" xsi:type="array">
+                <item name="transactionType" xsi:type="string">Refund</item>
+                <item name="statusIsClosed" xsi:type="string">Yes</item>
+            </data>
+            <data name="transactions/Capture" xsi:type="array">
+                <item name="transactionType" xsi:type="string">Capture</item>
+                <item name="statusIsClosed" xsi:type="string">Yes</item>
+            </data>
+            <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data>
+            <constraint name="Magento\Sales\Test\Constraint\AssertRefundSuccessCreateMessage" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertRefundInCommentsHistory" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertRefundInCreditMemoTab" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertTransactionStatus" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.xml
index 1d92fa149efbc336eb0910a451a1740f2eda6c14..6005fe4008d7bb52308878e81a7d0211c5441a87 100644
--- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.xml
@@ -27,7 +27,7 @@
             </data>
             <data name="payment/method" xsi:type="string">paypal_express</data>
             <data name="configData" xsi:type="string">paypal_express, freeshipping</data>
-            <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data>
+            <data name="tag" xsi:type="string">test_type:3rd_party_test_deprecated, severity:S0</data>
             <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" />
             <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" />
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.xml
index 38c876719bc3d82c772ff6f86cd507229ec5cf2b..233958afa1aa5605f922b105b2da85dee08960c8 100644
--- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.xml
@@ -28,7 +28,7 @@
                 <item name="grandTotal" xsi:type="string">145.98</item>
             </data>
             <data name="configData" xsi:type="string">payflowpro</data>
-            <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data>
+            <data name="tag" xsi:type="string">test_type:3rd_party_test_deprecated, severity:S0</data>
             <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" />
             <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" />
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.xml
index e52ed631ae46f983dc8860e7bf628f95a5a6a7fb..7de72c8ac9d93143dd3d59595a452981f2e15a89 100644
--- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.xml
@@ -26,7 +26,7 @@
             </data>
             <data name="payment/method" xsi:type="string">paypal_express</data>
             <data name="configData" xsi:type="string">paypal_express</data>
-            <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data>
+            <data name="tag" xsi:type="string">test_type:3rd_party_test_deprecated, severity:S0</data>
             <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" />
             <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" />
@@ -51,7 +51,7 @@
             </data>
             <data name="payment/method" xsi:type="string">paypal_express</data>
             <data name="configData" xsi:type="string">payflowlink</data>
-            <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data>
+            <data name="tag" xsi:type="string">test_type:3rd_party_test_deprecated, severity:S0</data>
             <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" />
             <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" />
@@ -76,7 +76,7 @@
             </data>
             <data name="payment/method" xsi:type="string">paypal_express</data>
             <data name="configData" xsi:type="string">paypal_express</data>
-            <data name="tag" xsi:type="string">test_type:3rd_party_test</data>
+            <data name="tag" xsi:type="string">test_type:3rd_party_test_deprecated</data>
             <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" />
             <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" />
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutDeclinedTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutDeclinedTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e015e3ba566648ce05326e3fae03bf2a76eefc64
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutDeclinedTest.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\Checkout\Test\TestCase\OnePageCheckoutDeclinedTest" summary="Error message during OnePageCheckout">
+        <variation name="OnePageCheckoutPayflowProWithAVSStreetDoesNotMatch" summary="Place Order via Payflow Pro with AVS Street verification fail" ticketId="MAGETWO-37480">
+            <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data>
+            <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data>
+            <data name="customer/dataset" xsi:type="string">default</data>
+            <data name="shippingAddress/dataset" xsi:type="string">AVS_street_does_not_match_address</data>
+            <data name="checkoutMethod" xsi:type="string">guest</data>
+            <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data>
+            <data name="shipping/shipping_method" xsi:type="string">Fixed</data>
+            <data name="payment/method" xsi:type="string">payflowpro</data>
+            <data name="creditCard/dataset" xsi:type="string">visa_default</data>
+            <data name="configData" xsi:type="string">payflowpro, payflowpro_avs_street_does_not_match</data>
+            <data name="expectedErrorMessage" xsi:type="string">An error occurred on the server. Please try to place the order again.</data>
+            <constraint name="Magento\Checkout\Test\Constraint\AssertCheckoutErrorMessage" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml
index 655b2f5f9d3fb83eaca544d74db4e9adf0732bbe..44577748f7b7a1abe37e6a9e562b3059820b0267 100644
--- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml
@@ -55,7 +55,7 @@
             <constraint name="Magento\Sales\Test\Constraint\AssertAuthorizationInCommentsHistory" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderPaymentInformation" />
         </variation>
-        <variation name="OnePageCheckoutPayflowProWithAVSStreetMatches" summary="Place Order via Payflow Pro with success AVS Street verification" ticketId="MAGETWO-37479">
+        <variation name="OnePageCheckoutPayflowProWithAVSStreetMatch" summary="Place Order via Payflow Pro with success AVS Street verification" ticketId="MAGETWO-37479">
             <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data>
             <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data>
             <data name="customer/dataset" xsi:type="string">default</data>
@@ -80,5 +80,24 @@
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderPaymentInformation" />
         </variation>
+        <variation name="OnePageCheckoutPayPalPaymentsPro" summary="Guest Checkout using PayPal Payments Pro and Flat Rate" ticketId="MAGETWO-62039">
+            <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data>
+            <data name="customer/dataset" xsi:type="string">default</data>
+            <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data>
+            <data name="checkoutMethod" xsi:type="string">guest</data>
+            <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data>
+            <data name="shipping/shipping_method" xsi:type="string">Fixed</data>
+            <data name="payment/method" xsi:type="string">payflowpro</data>
+            <data name="prices" xsi:type="array">
+                <item name="grandTotal" xsi:type="string">15.00</item>
+            </data>
+            <data name="creditCard/dataset" xsi:type="string">visa_default</data>
+            <data name="configData" xsi:type="string">paypal_direct</data>
+            <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data>
+            <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" />
+            <constraint name="Magento\Checkout\Test\Constraint\AssertCartIsEmpty" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertAuthorizationInCommentsHistory" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/AbstractItems.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/AbstractItems.php
index d7a89b68c553808cfdbb7de9854ce37e82464618..38ad9139d4fdb2bf28c40d8420db890dcda77d3a 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/AbstractItems.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/AbstractItems.php
@@ -19,63 +19,63 @@ class AbstractItems extends Block
      *
      * @var string
      */
-    private $rowItem = 'tbody';
+    protected $rowItem = 'tbody';
 
     /**
      * Locator for product sku column.
      *
      * @var string
      */
-    private $sku = '.col-product .product-sku-block';
+    protected $sku = '.col-product .product-sku-block';
 
     /**
      * Locator for product title column.
      *
      * @var string
      */
-    private $title = '.col-product .product-title';
+    protected $title = '.col-product .product-title';
 
     /**
      * Locator for "Price" column.
      *
      * @var string
      */
-    private $price = '.col-price .price';
+    protected $price = '.col-price .price';
 
     /**
      * Locator for "Qty" column.
      *
      * @var string
      */
-    private $qty = '.col-qty';
+    protected $qty = '.col-qty';
 
     /**
      * Locator for "Subtotal" column.
      *
      * @var string
      */
-    private $subtotal = '.col-subtotal .price';
+    protected $subtotal = '.col-subtotal .price';
 
     /**
      * Locator for "Tax Amount" column.
      *
      * @var string
      */
-    private $taxAmount = '.col-tax .price';
+    protected $taxAmount = '.col-tax .price';
 
     /**
      * Locator for "Discount Amount" column.
      *
      * @var string
      */
-    private $discountAmount = '.col-discount .price';
+    protected $discountAmount = '.col-discount .price';
 
     /**
      * Locator for "Row total" column.
      *
      * @var string
      */
-    private $rowTotal = '.col-total .price';
+    protected $rowTotal = '.col-total .price';
 
     /**
      * Get items data.
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/CreditMemos/Grid.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/CreditMemos/Grid.php
index 53833125dce7ff55eded48828046c5a047a83cc9..1cfad8033bd5755df01975559682db88c4b26d61 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/CreditMemos/Grid.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/CreditMemos/Grid.php
@@ -6,11 +6,13 @@
 
 namespace Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\CreditMemos;
 
+use Magento\Mtf\Client\Locator;
+use Magento\Ui\Test\Block\Adminhtml\DataGrid;
+
 /**
- * Class Grid
- * Credit memos grid on order view page
+ * Credit memos grid on order view page.
  */
-class Grid extends \Magento\Backend\Test\Block\Widget\Grid
+class Grid extends DataGrid
 {
     /**
      * Base part of row locator template for getRow() method.
@@ -20,14 +22,28 @@ class Grid extends \Magento\Backend\Test\Block\Widget\Grid
     protected $rowPattern = './/tr[%s]';
 
     /**
-     * Locator value for link in action column
+     * Locator value for link in action column.
      *
      * @var string
      */
     protected $editLink = 'tbody td[data-column="increment_id"]';
 
     /**
-     * Filters array mapping
+     * Css selector for credit memo ids.
+     *
+     * @var string
+     */
+    protected $creditMemoId = 'tbody td:nth-child(2)';
+
+    /**
+     * CreditMemos data grid loader Xpath locator.
+     *
+     * @var string
+     */
+    protected $loader = '//div[contains(@data-component, "sales_order_view_creditmemo_grid")]';
+
+    /**
+     * Filters array mapping.
      *
      * @var array
      */
@@ -48,24 +64,26 @@ class Grid extends \Magento\Backend\Test\Block\Widget\Grid
     ];
 
     /**
-     * Get credit memo id from grid
+     * Get credit memo id from grid.
      *
      * @return array|string
      */
     public function getCreditMemoId()
     {
-        return $this->_rootElement->find($this->editLink)->getText();
+        $this->waitForElementNotVisible($this->loader, Locator::SELECTOR_XPATH);
+        return $this->_rootElement->find($this->creditMemoId)->getText();
     }
 
     /**
-     * Get credit memo ids
+     * Get credit memo ids.
      *
      * @return array
      */
     public function getIds()
     {
         $result = [];
-        $creditMemoIds = $this->_rootElement->getElements($this->editLink);
+        $this->waitForElementNotVisible($this->loader, Locator::SELECTOR_XPATH);
+        $creditMemoIds = $this->_rootElement->getElements($this->creditMemoId);
         foreach ($creditMemoIds as $creditMemoId) {
             $result[] = trim($creditMemoId->getText());
         }
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php
index 41fbd8979b58df8fb58f000e3ea79e0f289344c4..c036067b3bbf270fba7353d48dfa75bf1f2a0e56 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php
@@ -6,6 +6,8 @@
 
 namespace Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Invoices;
 
+use Magento\Mtf\Client\Locator;
+
 /**
  * Invoices grid on order view page.
  */
@@ -19,18 +21,18 @@ class Grid extends \Magento\Ui\Test\Block\Adminhtml\DataGrid
     protected $editLink = '[data-column="increment_id"]';
 
     /**
-     * Locator for invoice ids
+     * Css selector for invoice ids.
      *
      * @var string
      */
     protected $invoiceId = 'tbody td:nth-child(2)';
 
     /**
-     * Invoices data grid loader locator.
+     * Invoices data grid loader Xpath locator.
      *
      * @var string
      */
-    protected $loader = '[data-component="sales_order_view_invoice_grid"]';
+    protected $loader = '//div[contains(@data-component, "sales_order_view_invoice_grid")]';
 
     /**
      * Filters array mapping.
@@ -64,7 +66,7 @@ class Grid extends \Magento\Ui\Test\Block\Adminhtml\DataGrid
     public function getIds()
     {
         $result = [];
-        $this->waitForElementNotVisible($this->loader);
+        $this->waitForElementNotVisible($this->loader, Locator::SELECTOR_XPATH);
         $invoiceIds = $this->_rootElement->getElements($this->invoiceId);
         foreach ($invoiceIds as $invoiceId) {
             $result[] = trim($invoiceId->getText());
@@ -80,7 +82,7 @@ class Grid extends \Magento\Ui\Test\Block\Adminhtml\DataGrid
      */
     public function viewInvoice()
     {
-        $this->waitForElementNotVisible($this->loader);
+        $this->waitForElementNotVisible($this->loader, Locator::SELECTOR_XPATH);
         $this->_rootElement->find($this->invoiceId)->click();
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Shipments/Grid.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Shipments/Grid.php
index 7589e0d82f4e530cd1e58f561da0b01510af5235..f92594bec680776e72fac29435dfac72ccef6ec6 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Shipments/Grid.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Shipments/Grid.php
@@ -6,34 +6,43 @@
 
 namespace Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Shipments;
 
+use Magento\Mtf\Client\Locator;
+use Magento\Ui\Test\Block\Adminhtml\DataGrid;
+
 /**
- * Class Grid
- * Shipments grid on order view page
+ * Shipments grid on order view page.
  */
-class Grid extends \Magento\Backend\Test\Block\Widget\Grid
+class Grid extends DataGrid
 {
     /**
-     * Locator value for link in action column
+     * Locator value for link in action column.
      *
      * @var string
      */
     protected $editLink = '[data-column="real_shipment_id"]';
 
     /**
-     * Locator for shipment ids
+     * Css selector for shipment ids.
+     *
+     * @var string
+     */
+    protected $shipmentId = 'tbody td:nth-child(2)';
+
+    /**
+     * Shipments data grid loader Xpath locator.
      *
      * @var string
      */
-    protected $shipmentId = 'tbody td[data-column="real_shipment_id"]';
+    protected $loader = '//div[contains(@data-component, "sales_order_view_shipment_grid")]';
 
     /**
-     * Filters array mapping
+     * Filters array mapping.
      *
      * @var array
      */
     protected $filters = [
         'id' => [
-            'selector' => 'input[name="real_shipment_id"]',
+            'selector' => 'input[name="increment_id"]',
         ],
         'qty_from' => [
             'selector' => '[name="total_qty[from]"]',
@@ -44,13 +53,14 @@ class Grid extends \Magento\Backend\Test\Block\Widget\Grid
     ];
 
     /**
-     * Get shipment ids
+     * Get shipment ids.
      *
      * @return array
      */
     public function getIds()
     {
         $result = [];
+        $this->waitForElementNotVisible($this->loader, Locator::SELECTOR_XPATH);
         $shipmentIds = $this->_rootElement->getElements($this->shipmentId);
         foreach ($shipmentIds as $shipmentId) {
             $result[] = trim($shipmentId->getText());
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceNotInInvoicesGrid.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceNotInInvoicesGrid.php
new file mode 100644
index 0000000000000000000000000000000000000000..fd6347e481c9c24d1ee73ed7fc6ccac4578417c6
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceNotInInvoicesGrid.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Sales\Test\Constraint;
+
+use Magento\Sales\Test\Fixture\OrderInjectable;
+use Magento\Sales\Test\Page\Adminhtml\InvoiceIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that invoice with corresponding order ID is absent in the invoices grid.
+ */
+class AssertInvoiceNotInInvoicesGrid extends AbstractConstraint
+{
+    /* tags */
+    const SEVERITY = 'low';
+    /* end tags */
+
+    /**
+     * Assert that invoice with corresponding order ID is absent in the invoices grid.
+     *
+     * @param InvoiceIndex $invoiceIndex
+     * @param OrderInjectable $order
+     * @param array $ids
+     * @return void
+     */
+    public function processAssert(InvoiceIndex $invoiceIndex, OrderInjectable $order, array $ids)
+    {
+        $invoiceIndex->open();
+        $amount = $order->getPrice();
+        $orderId = $order->getId();
+        foreach ($ids['invoiceIds'] as $key => $invoiceId) {
+            $filter = [
+                'id' => $invoiceId,
+                'order_id' => $orderId,
+                'grand_total_from' => $amount[$key]['grand_invoice_total'],
+                'grand_total_to' => $amount[$key]['grand_invoice_total'],
+            ];
+            $invoiceIndex->getInvoicesGrid()->search($filter);
+            $filter['grand_total_from'] = number_format($amount[$key]['grand_invoice_total'], 2);
+            $filter['grand_total_to'] = number_format($amount[$key]['grand_invoice_total'], 2);
+            \PHPUnit_Framework_Assert::assertFalse(
+                $invoiceIndex->getInvoicesGrid()->isRowVisible($filter, false, false),
+                'Invoice is present in invoices grid on invoice index page.'
+            );
+        }
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Invoice is absent in the invoices grid on invoice index page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusIsCanceled.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusIsCanceled.php
new file mode 100644
index 0000000000000000000000000000000000000000..2547cb49b70a447382033b2d76f7606d5545f459
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusIsCanceled.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Sales\Test\Constraint;
+
+use Magento\Sales\Test\Page\Adminhtml\OrderIndex;
+use Magento\Sales\Test\Page\Adminhtml\SalesOrderView;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that status is Canceled.
+ */
+class AssertOrderStatusIsCanceled extends AbstractConstraint
+{
+    /**
+     * Assert that status is Canceled.
+     *
+     * @param OrderIndex $salesOrder
+     * @param SalesOrderView $salesOrderView
+     * @return void
+     */
+    public function processAssert(
+        OrderIndex $salesOrder,
+        SalesOrderView $salesOrderView
+    ) {
+        $salesOrder->open();
+        $grid = $salesOrder->getSalesOrderGrid();
+        $grid->resetFilter();
+        $grid->sortByColumn('ID');
+        $grid->sortGridByField('ID');
+        $grid->openFirstRow();
+
+        /** @var \Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Info $infoTab */
+        $infoTab = $salesOrderView->getOrderForm()->openTab('info')->getTab('info');
+        \PHPUnit_Framework_Assert::assertEquals(
+            $infoTab->getOrderStatus(),
+            'Canceled'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Order status is correct.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertProductQtyDecreased.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertProductQtyDecreased.php
new file mode 100644
index 0000000000000000000000000000000000000000..0d754dcfcd8f67ba93c602381ec0ed0a213937f0
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertProductQtyDecreased.php
@@ -0,0 +1,105 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Sales\Test\Constraint;
+
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Mtf\Fixture\FixtureInterface;
+use Magento\Mtf\ObjectManager;
+use Magento\Mtf\System\Event\EventManagerInterface;
+use Magento\Sales\Test\Fixture\OrderInjectable;
+
+/**
+ * Assert that product quantity is decreased after placing an order.
+ */
+class AssertProductQtyDecreased extends AbstractConstraint
+{
+    /**
+     * @var FixtureFactory
+     */
+    protected $fixtureFactory;
+
+    /**
+     * Skip fields for create product fixture.
+     *
+     * @var array
+     */
+    protected $skipFields = [
+        'attribute_set_id',
+        'website_ids',
+        'checkout_data',
+        'type_id',
+        'price',
+    ];
+
+    /**
+     * AssertProductQtyDecreased constructor.
+     *
+     * @param ObjectManager $objectManager
+     * @param EventManagerInterface $eventManager
+     * @param FixtureFactory $fixtureFactory
+     */
+    public function __construct(
+        ObjectManager $objectManager,
+        EventManagerInterface $eventManager,
+        FixtureFactory $fixtureFactory
+    ) {
+        $this->fixtureFactory = $fixtureFactory;
+        parent::__construct($objectManager, $eventManager);
+    }
+
+    /**
+     * Assert form data equals fixture data.
+     *
+     * @param OrderInjectable $order
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductEdit $productPage
+     * @return void
+     */
+    public function processAssert(
+        OrderInjectable $order,
+        CatalogProductIndex $productGrid,
+        CatalogProductEdit $productPage
+    ) {
+        $product = $this->getProduct($order);
+        $this->objectManager->get(\Magento\Catalog\Test\Constraint\AssertProductForm::class)->processAssert(
+            $product,
+            $productGrid,
+            $productPage
+        );
+    }
+
+    /**
+     * Get product's fixture.
+     *
+     * @param OrderInjectable $order
+     * @param int $index [optional]
+     * @return FixtureInterface
+     */
+    protected function getProduct(OrderInjectable $order, $index = 0)
+    {
+        $product = $order->getEntityId()['products'][$index];
+        $productData = $product->getData();
+        $checkoutDataQty = isset($productData['checkout_data']['qty']) ? $productData['checkout_data']['qty'] : 1;
+        $productData['quantity_and_stock_status']['qty'] -= $checkoutDataQty;
+
+        $productData = array_diff_key($productData, array_flip($this->skipFields));
+
+        return $this->fixtureFactory->create(get_class($product), ['data' => $productData]);
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Product qty was decreased after placing an order.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertProductsQtyAfterOrderCancel.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertProductsQtyAfterOrderCancel.php
new file mode 100644
index 0000000000000000000000000000000000000000..028cf9b9267e39aa65e0a7674bd2f969ca495c35
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertProductsQtyAfterOrderCancel.php
@@ -0,0 +1,128 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Sales\Test\Constraint;
+
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Sales\Test\Fixture\OrderInjectable;
+use Magento\Bundle\Test\Fixture\BundleProduct;
+use Magento\ConfigurableProduct\Test\Fixture\ConfigurableProduct;
+use Magento\Catalog\Test\Constraint\AssertProductForm;
+use Magento\ConfigurableProduct\Test\Constraint\AssertConfigurableProductForm;
+
+/**
+ * Assert that products quantity was increased after order cancel.
+ */
+class AssertProductsQtyAfterOrderCancel extends AbstractConstraint
+{
+    /**
+     * Skip fields for create product fixture.
+     *
+     * @var array
+     */
+    protected $skipFields = [
+        'attribute_set_id',
+        'website_ids',
+        'checkout_data',
+        'type_id',
+        'price',
+    ];
+
+    /**
+     * Assert form data equals fixture data.
+     *
+     * @param OrderInjectable $order
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductEdit $productPage
+     * @param FixtureFactory $fixtureFactory
+     * @param AssertProductForm $assertProductForm
+     * @param AssertConfigurableProductForm $assertConfigurableProductForm
+     * @return void
+     */
+    public function processAssert(
+        OrderInjectable $order,
+        CatalogProductIndex $productGrid,
+        CatalogProductEdit $productPage,
+        FixtureFactory $fixtureFactory,
+        AssertProductForm $assertProductForm,
+        AssertConfigurableProductForm $assertConfigurableProductForm
+    ) {
+        for ($i = 0; $i < count($order->getEntityId()['products']); $i++) {
+            $product = $order->getEntityId()['products'][$i];
+            $productData = $product->getData();
+            if ($product instanceof BundleProduct) {
+                $this->assertBundleProduct($product, $productGrid, $productPage, $fixtureFactory, $assertProductForm);
+            } elseif ($product instanceof ConfigurableProduct) {
+                $assertConfigurableProductForm->processAssert(
+                    $fixtureFactory->create(
+                        get_class($product),
+                        ['data' => array_diff_key($productData, array_flip($this->skipFields))]
+                    ),
+                    $productGrid,
+                    $productPage
+                );
+            } else {
+                $assertProductForm->processAssert(
+                    $fixtureFactory->create(
+                        get_class($product),
+                        ['data' => array_diff_key($productData, array_flip($this->skipFields))]
+                    ),
+                    $productGrid,
+                    $productPage
+                );
+            }
+        }
+    }
+
+    /**
+     * Assert quantity of products that are part of the bundle product.
+     *
+     * @param BundleProduct $product
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductEdit $productPage
+     * @param FixtureFactory $fixtureFactory
+     * @param AssertProductForm $assertProductForm
+     * @return void
+     */
+    public function assertBundleProduct(
+        BundleProduct $product,
+        CatalogProductIndex $productGrid,
+        CatalogProductEdit $productPage,
+        FixtureFactory $fixtureFactory,
+        AssertProductForm $assertProductForm
+    ) {
+        $productData = $product->getData();
+        $bundleSelections = $product->getDataFieldConfig('bundle_selections')['source']->getProducts();
+        foreach ($bundleSelections as $key => $selection) {
+            $valueName = $productData['checkout_data']['options']['bundle_options'][$key]['value']['name'];
+            foreach ($selection as $item) {
+                if (strpos($item->getName(), $valueName) !== false) {
+                    $assertProductForm->processAssert(
+                        $fixtureFactory->create(
+                            get_class($product),
+                            ['data' => array_diff_key($item->getData(), array_flip($this->skipFields))]
+                        ),
+                        $productGrid,
+                        $productPage
+                    );
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Products quantity was reverted after order cancel.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertRefundNotInRefundsGrid.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertRefundNotInRefundsGrid.php
new file mode 100644
index 0000000000000000000000000000000000000000..c754d6529c0ef04a1a6f4e307cd151de917eb871
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertRefundNotInRefundsGrid.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Sales\Test\Constraint;
+
+use Magento\Sales\Test\Fixture\OrderInjectable;
+use Magento\Sales\Test\Page\Adminhtml\CreditMemoIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that refund is absent in the refunds grid.
+ */
+class AssertRefundNotInRefundsGrid extends AbstractConstraint
+{
+    /**
+     * Assert that refund is absent in the refunds grid.
+     *
+     * @param CreditMemoIndex $creditMemoIndex
+     * @param OrderInjectable $order
+     * @param array $ids
+     * @return void
+     */
+    public function processAssert(CreditMemoIndex $creditMemoIndex, OrderInjectable $order, array $ids)
+    {
+        $creditMemoIndex->open();
+        $amount = $order->getPrice();
+        $orderId = $order->getId();
+        foreach ($ids['creditMemoIds'] as $key => $creditMemoId) {
+            $filter = [
+                'id' => $creditMemoId,
+                'order_id' => $orderId,
+                'grand_total_from' => $amount[$key]['grand_creditmemo_total'],
+                'grand_total_to' => $amount[$key]['grand_creditmemo_total'],
+            ];
+            $creditMemoIndex->getCreditMemoGrid()->search($filter);
+            $filter['grand_total_from'] = number_format($amount[$key]['grand_creditmemo_total'], 2);
+            $filter['grand_total_to'] = number_format($amount[$key]['grand_creditmemo_total'], 2);
+            \PHPUnit_Framework_Assert::assertFalse(
+                $creditMemoIndex->getCreditMemoGrid()->isRowVisible($filter, false, false),
+                "Credit memo '#$creditMemoId' is present in credit memos grid on credit memo index page."
+            );
+        }
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Credit memo is absent in credit memos grid on credit memo index page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Fixture/OrderInjectable/StoreId.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Fixture/OrderInjectable/StoreId.php
index 1e393033ffb057e53786a84f776cefbf9d50dbeb..2b6771b59d324de90b77ceef50991ab11112afab 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/Fixture/OrderInjectable/StoreId.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Fixture/OrderInjectable/StoreId.php
@@ -7,6 +7,7 @@
 namespace Magento\Sales\Test\Fixture\OrderInjectable;
 
 use Magento\Store\Test\Fixture\Store;
+use Magento\Store\Test\Fixture\Website;
 use Magento\Mtf\Fixture\FixtureFactory;
 use Magento\Mtf\Fixture\DataSource;
 
@@ -22,6 +23,13 @@ class StoreId extends DataSource
      */
     public $store;
 
+    /**
+     * Website fixture.
+     *
+     * @var Website
+     */
+    private $website;
+
     /**
      * @constructor
      * @param FixtureFactory $fixtureFactory
@@ -31,20 +39,33 @@ class StoreId extends DataSource
     public function __construct(FixtureFactory $fixtureFactory, array $data, array $params = [])
     {
         $this->params = $params;
-
         $storeData =  isset($data['dataset']) ? ['dataset' => $data['dataset']] : [];
         if (isset($data['data'])) {
             $storeData = array_replace_recursive($storeData, $data);
         }
 
-        if ($storeData) {
-            $store = $fixtureFactory->createByCode('store', $storeData);
-            /** @var Store $store */
-            if (!$store->getStoreId()) {
-                $store->persist();
+        if (isset($data['store'])) {
+            $this->store = $data['store'];
+            $website = $data['store']->getDataFieldConfig('group_id')['source']
+                ->getStoreGroup()->getDataFieldConfig('website_id')['source']->getWebsite();
+            $this->website = $website;
+            $this->data = $data['store']->getName();
+        } else {
+            if ($storeData) {
+                $store = $fixtureFactory->createByCode('store', $storeData);
+                /** @var Store $store */
+                if (!$store->getStoreId()) {
+                    $store->persist();
+                }
+                if (isset($store->getData()['group_id'])) {
+                    $website = $store->getDataFieldConfig('group_id')['source']
+                        ->getStoreGroup()->getDataFieldConfig('website_id')['source']->getWebsite();
+                    $this->website = $website;
+                }
+
+                $this->store = $store;
+                $this->data = $store->getName();
             }
-            $this->store = $store;
-            $this->data = $store->getName();
         }
     }
 
@@ -57,4 +78,17 @@ class StoreId extends DataSource
     {
         return $this->store;
     }
+
+    /**
+     * Return Website fixture.
+     *
+     * @return Website|null
+     */
+    public function getWebsite()
+    {
+        if (isset($this->website)) {
+            return $this->website;
+        }
+        return null;
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Webapi.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Webapi.php
index 1286064662ebe097ae1239da04419ac1bad8b8a9..f0d63f71e7aa4b349147852bf0746b9676337a3b 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Webapi.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Webapi.php
@@ -68,9 +68,8 @@ class Webapi extends AbstractWebapi implements OrderInjectableInterface
 
         /** @var OrderInjectable $fixture */
         $this->createQuote($fixture);
-
         $url = $this->isCustomerGuest ? 'guest-carts/' . $this->quote  : 'carts/' . (int)$this->quote;
-        $this->url = $_ENV['app_frontend_url'] . 'rest/V1/' . $url;
+        $this->url = $_ENV['app_frontend_url'] . $this->prepareWebsiteUrl($fixture) . '/V1/' . $url;
 
         $this->setProducts($fixture);
         $this->setCoupon($fixture);
@@ -78,8 +77,9 @@ class Webapi extends AbstractWebapi implements OrderInjectableInterface
         $this->setShippingInformation($fixture);
         $this->setPaymentMethod($fixture);
         $orderId = $this->placeOrder();
+        $orderIncrementId = $this->getOrderIncrementId($orderId);
 
-        return ['id' => sprintf("%09d", $orderId)];
+        return ['id' => $orderIncrementId];
     }
 
     /**
@@ -92,7 +92,7 @@ class Webapi extends AbstractWebapi implements OrderInjectableInterface
     protected function createQuote(OrderInjectable $order)
     {
         if ($this->isCustomerGuest) {
-            $url = $_ENV['app_frontend_url'] . 'rest/V1/guest-carts';
+            $url = $_ENV['app_frontend_url'] . $this->prepareWebsiteUrl($order) . '/V1/guest-carts';
             $this->webapiTransport->write($url);
             $response = json_decode($this->webapiTransport->read(), true);
             $this->webapiTransport->close();
@@ -102,7 +102,8 @@ class Webapi extends AbstractWebapi implements OrderInjectableInterface
             }
             $this->quote = $response;
         } else {
-            $url = $_ENV['app_frontend_url'] . 'rest/V1/customers/' . $order->getCustomerId()->getId() . '/carts';
+            $url = $_ENV['app_frontend_url'] . $this->prepareWebsiteUrl($order)
+                . '/V1/customers/' . $order->getCustomerId()->getId() . '/carts';
             $data = '{"customerId": "' . $order->getCustomerId()->getId() . '"}';
             $this->webapiTransport->write($url, $data);
             $response = json_decode($this->webapiTransport->read(), true);
@@ -357,4 +358,41 @@ class Webapi extends AbstractWebapi implements OrderInjectableInterface
 
         return ['extension_attributes' => ['downloadable_option' => ['downloadable_links' => $links]]];
     }
+
+    /**
+     * Prepare url for placing order in custom website.
+     *
+     * @param OrderInjectable $order
+     * @return string
+     */
+    private function prepareWebsiteUrl(OrderInjectable $order)
+    {
+        $url = 'rest';
+        if ($website = $order->getDataFieldConfig('store_id')['source']->getWebsite()) {
+            $store = $order->getDataFieldConfig('store_id')['source']->getStore();
+            $url = 'websites/' . $website->getCode() . '/rest/' . $store->getCode();
+        }
+        return $url;
+    }
+
+    /**
+     * Retrieve order increment id.
+     *
+     * @param int $orderId
+     * @return string
+     * @throws \Exception
+     */
+    private function getOrderIncrementId($orderId)
+    {
+        $url = $_ENV['app_frontend_url'] . 'rest/V1/orders/' . $orderId;
+        $this->webapiTransport->write($url, [], WebapiDecorator::GET);
+        $response = json_decode($this->webapiTransport->read(), true);
+        $this->webapiTransport->close();
+
+        if (!$response['increment_id']) {
+            $this->eventManager->dispatchEvent(['webapi_failed'], [$response]);
+            throw new \Exception('Could not get order details using web API.');
+        }
+        return $response['increment_id'];
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Page/Adminhtml/OrderCreateIndex.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/Page/Adminhtml/OrderCreateIndex.xml
index f80715543de67036849b982ec0defa92ba66af4a..6ef15dc192dab91f5279b80539d29e4e34c28500 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/Page/Adminhtml/OrderCreateIndex.xml
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Page/Adminhtml/OrderCreateIndex.xml
@@ -14,5 +14,6 @@
     <block name="couponsBlock" class="Magento\Sales\Test\Block\Adminhtml\Order\Create\Coupons" locator="#order-coupons" strategy="css selector"/>
     <block name="customerActivitiesBlock" class="Magento\Sales\Test\Block\Adminhtml\Order\Create\CustomerActivities" locator=".customer-current-activity" strategy="css selector"/>
     <block name="configureProductBlock" class="Magento\Catalog\Test\Block\Adminhtml\Product\Composite\Configure" locator="//*[@data-role='modal' and .//*[@id='product_composite_configure'] and contains(@class,'_show')]" strategy="xpath"/>
+    <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator="#messages .messages" strategy="css selector"/>
   </page>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Repository/OrderInjectable.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/Repository/OrderInjectable.xml
index 65335ced8ed4c24f2bee701f1be039274585fd55..462f55af64fb5852a1c5f4501cb225e88a879030 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/Repository/OrderInjectable.xml
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Repository/OrderInjectable.xml
@@ -251,5 +251,32 @@
             <field name="base_currency_code" xsi:type="string">0</field>
             <field name="order_currency_code" xsi:type="string">USD</field>
         </dataset>
+
+        <dataset name="custom_store_order">
+            <field name="entity_id" xsi:type="array">
+                <item name="products" xsi:type="string">catalogProductSimple::default</item>
+            </field>
+            <field name="customer_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="billing_address_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">US_address</item>
+            </field>
+            <field name="store_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">custom_store</item>
+            </field>
+            <field name="shipping_method" xsi:type="string">flatrate_flatrate</field>
+            <field name="payment_auth_expiration" xsi:type="array">
+                <item name="method" xsi:type="string">checkmo</item>
+            </field>
+            <field name="payment_authorization_amount" xsi:type="array">
+                <item name="method" xsi:type="string">free</item>
+            </field>
+            <field name="base_currency_code" xsi:type="string">0</field>
+            <field name="order_currency_code" xsi:type="string">USD</field>
+            <field name="price" xsi:type="array">
+                <item name="dataset" xsi:type="string">full_flow</item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Repository/OrderInjectable/Price.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/Repository/OrderInjectable/Price.xml
index 3da1f91925e0a1274cbe317d36f2bc40271cbeb6..64e2f8808172492ca82dc8cb545f33a0554a3fc5 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/Repository/OrderInjectable/Price.xml
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Repository/OrderInjectable/Price.xml
@@ -19,6 +19,13 @@
             </field>
         </dataset>
 
+        <dataset name="full_invoice_with_product_10_dollar">
+            <field name="0" xsi:type="array">
+                <item name="grand_order_total" xsi:type="string">15</item>
+                <item name="grand_invoice_total" xsi:type="string">15</item>
+            </field>
+        </dataset>
+
         <dataset name="partial_invoice">
             <field name="0" xsi:type="array">
                 <item name="grand_order_total" xsi:type="string">210</item>
@@ -50,5 +57,13 @@
                 <item name="grand_invoice_total" xsi:type="string">0</item>
             </field>
         </dataset>
+
+        <dataset name="full_flow">
+            <field name="0" xsi:type="array">
+                <item name="grand_creditmemo_total" xsi:type="string">565</item>
+                <item name="grand_invoice_total" xsi:type="string">565</item>
+                <item name="grand_order_total" xsi:type="string">565</item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.php
index 71575ffb16b858cd43353c02d82f2d496eac4a51..4c56bc61d291105ffd58db9efd0a0624c89e7e54 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.php
@@ -48,6 +48,13 @@ class CancelCreatedOrderTest extends Injectable
      */
     protected $salesOrderView;
 
+    /**
+     * Configuration setting.
+     *
+     * @var string
+     */
+    private $configData;
+
     /**
      * Inject pages.
      *
@@ -72,6 +79,7 @@ class CancelCreatedOrderTest extends Injectable
     public function test(OrderInjectable $order, TestStepFactory $stepFactory, $configData)
     {
         // Preconditions
+        $this->configData = $configData;
         $stepFactory->create(
             \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
             ['configData' => $configData]
@@ -87,4 +95,17 @@ class CancelCreatedOrderTest extends Injectable
             'customer' => $order->getDataFieldConfig('customer_id')['source']->getCustomer(),
         ];
     }
+
+    /**
+     * Reset config settings to default.
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData, 'rollback' => true]
+        )->run();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml
index e839681907c6d291b0855f138fa7d52c9b1dd4fa..46dc7ecf646aaafa4f8daff73b6567aeb5b1a464 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CancelCreatedOrderTest.xml
@@ -7,14 +7,14 @@
  -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
     <testCase name="Magento\Sales\Test\TestCase\CancelCreatedOrderTest" summary="Cancel Created Order for Offline Payment Methods" ticketId="MAGETWO-28191">
-        <variation name="CancelCreatedOrderTestVariationWithCheckMoneyOrderPaymentMethod" summary="Cancel order with check/money order payment method and check status on storefront">
-            <data name="tag" xsi:type="string">to_maintain:yes</data>
+        <variation name="CancelCreatedOrderTestVariationWithCheckMoneyOrderPaymentMethod" summary="Cancel order with check/money order payment method and check status on storefront" ticketId="MAGETWO-13647,MAGETWO-43318">
             <data name="order/dataset" xsi:type="string">default</data>
-            <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::default,catalogProductSimple::default</data>
+            <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::low_stock_product,catalogProductVirtual::virtual_low_stock,bundleProduct::bundle_low_stock,configurableProduct::configurable_low_stock</data>
             <data name="status" xsi:type="string">Canceled</data>
             <data name="configData" xsi:type="string">checkmo</data>
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderCancelSuccessMessage" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGrid" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertProductsQtyAfterOrderCancel" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" />
         </variation>
         <variation name="CancelCreatedOrderTestVariationWithZeroSubtotalCheckout" summary="Cancel order with zero subtotal checkout payment method and check status on storefront">
@@ -53,5 +53,12 @@
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderCancelSuccessMessage" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" />
         </variation>
+        <variation name="CancelCreatedOrderTestVariationProductQtyWithoutStockDecrease" summary="Check product qty after placing an order with Decrease Stock When Order is Placed = No" ticketId="MAGETWO-43321">
+            <data name="order/dataset" xsi:type="string">default</data>
+            <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::low_stock_product</data>
+            <data name="configData" xsi:type="string">decrease_stock_after_order_no</data>
+            <constraint name="Magento\Sales\Test\Constraint\AssertOrderCancelSuccessMessage" />
+            <constraint name="Magento\ConfigurableProduct\Test\Constraint\AssertConfigurableProductsQtyAfterReorder" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CloseOrderTest.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CloseOrderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1594cad95eff98633a9b6b1e47a4705912059370
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CloseOrderTest.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Sales\Test\TestCase;
+
+use Magento\Mtf\TestCase\Scenario;
+
+/**
+ * Preconditions:
+ * 1. Order is placed.
+ *
+ * Steps:
+ * 1. Log in to Admin.
+ * 2. Go to Sales > Orders page.
+ * 3. Open order.
+ * 4. Click 'Ship' button and submit shipment.
+ * 5. Click 'Invoice' button.
+ * 6. Select Amount=Capture Online.
+ * 7. Click 'Submit Invoice' button.
+ * 8. Perform assertions.
+ *
+ * @group Order_Management
+ * @ZephyrId MAGETWO-13015, MAGETWO-13020
+ */
+class CloseOrderTest extends Scenario
+{
+    /* tags */
+    const MVP = 'yes';
+    const TEST_TYPE = '3rd_party_test';
+    const SEVERITY = 'S0';
+    /* end tags */
+
+    /**
+     * Close order.
+     *
+     * @return void
+     */
+    public function test()
+    {
+        $this->executeScenario();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.php
index 92b341bef2675fe635f804da2d9a17c5eea54c49..5a0fcf0cc92528318b96e07309c9d602758745ce 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.php
@@ -62,7 +62,7 @@ class CreateCreditMemoEntityTest extends Injectable
      * @param FixtureFactory $fixtureFactory
      * @param OrderInjectable $order
      * @param array $data
-     * @param string $configData
+     * @param string|null $configData [optional]
      * @return array
      */
     public function test(
@@ -70,7 +70,7 @@ class CreateCreditMemoEntityTest extends Injectable
         FixtureFactory $fixtureFactory,
         OrderInjectable $order,
         array $data,
-        $configData
+        $configData = null
     ) {
         // Preconditions
         $this->fixtureFactory = $fixtureFactory;
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOnlineCreditMemoTest.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOnlineCreditMemoTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e11e1391a10e3442e1a92230615d7f1c0a2fbc4d
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOnlineCreditMemoTest.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Sales\Test\TestCase;
+
+use Magento\Mtf\TestCase\Scenario;
+
+/**
+ * Preconditions:
+ * 1. Complete a sales order with online payment method.
+ *
+ * Steps:
+ * 1. Log in to Admin.
+ * 2. Open order from preconditions.
+ * 3. Open created invoice.
+ * 3. Create credit memo.
+ * 4. Perform assertions.
+ *
+ * @group Order_Management
+ * @ZephyrId MAGETWO-13059
+ */
+class CreateOnlineCreditMemoTest extends Scenario
+{
+    /* tags */
+    const MVP = 'yes';
+    const TEST_TYPE = '3rd_party_test';
+    const SEVERITY = 'S0';
+    /* end tags */
+
+    /**
+     * Runs test for online credit memo creation for order placed with online payment method.
+     *
+     * @return void
+     */
+    public function test()
+    {
+        $this->executeScenario();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderBackendTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderBackendTest.xml
index 2fb8f91d6d99794a426a91663f7a8ccef531a916..80208482bafd45f07eed259f0160d1e168fdecc2 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderBackendTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOrderBackendTest.xml
@@ -27,6 +27,7 @@
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGrid" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertProductQtyDecreased" />
         </variation>
         <variation name="CreateOrderBackendTestVariation2">
             <data name="description" xsi:type="string">Create order with virtual product for registered UK customer using Check/Money Order payment method</data>
@@ -148,5 +149,21 @@
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" />
             <constraint name="Magento\Customer\Test\Constraint\AssertCustomerForm" />
         </variation>
+        <variation name="CreateOrderBackendTestVariation18" summary="Create order with condition available product qty = ordered product qty" ticketId="MAGETWO-12798">
+            <data name="products/0" xsi:type="string">catalogProductSimple::product_with_qty_25</data>
+            <data name="customer/dataset" xsi:type="string">default</data>
+            <data name="billingAddress/dataset" xsi:type="string">US_address_1_without_email</data>
+            <data name="saveAddress" xsi:type="string">No</data>
+            <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data>
+            <data name="shipping/shipping_method" xsi:type="string">Fixed</data>
+            <data name="prices" xsi:type="array">
+                <item name="grandTotal" xsi:type="string">375.00</item>
+            </data>
+            <data name="payment/method" xsi:type="string">cashondelivery</data>
+            <data name="configData" xsi:type="string">cashondelivery</data>
+            <constraint name="Magento\Sales\Test\Constraint\AssertOrderSuccessCreateMessage" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" />
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductsOutOfStock" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/CreateShipmentStep.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/CreateShipmentStep.php
index a6378dc44d6503334e40f9567a1db4e97fb81d8a..32425c8aea4cc29d9fd2c9630d6d40289598cf29 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/CreateShipmentStep.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/CreateShipmentStep.php
@@ -18,6 +18,11 @@ use Magento\Mtf\TestStep\TestStepInterface;
  */
 class CreateShipmentStep implements TestStepInterface
 {
+    /**
+     * Shipment column title.
+     */
+    const COLUMN_NAME = 'Shipment';
+
     /**
      * Orders Page.
      *
@@ -111,6 +116,15 @@ class CreateShipmentStep implements TestStepInterface
     public function getShipmentIds()
     {
         $this->salesOrderView->getOrderForm()->openTab('shipments');
-        return $this->salesOrderView->getOrderForm()->getTab('shipments')->getGridBlock()->getIds();
+        $this->salesOrderView->getOrderForm()->getTab('shipments')->getGridBlock()->resetFilter();
+        $shipmentIds = $this->salesOrderView->getOrderForm()->getTab('shipments')->getGridBlock()->getAllIds();
+        $incrementIds = [];
+        foreach ($shipmentIds as $shipmentId) {
+            $incrementIds[] = $this->salesOrderView->getOrderForm()
+                ->getTab('shipments')
+                ->getGridBlock()
+                ->getColumnValue($shipmentId, self::COLUMN_NAME);
+        }
+        return $incrementIds;
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/SubmitOrderStep.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/SubmitOrderStep.php
index 0a82770fab38bbe574b77b0bb4e08eadbdc01a3f..3967b6571baa6fb2255b4629db9b89ada1e5d04c 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/SubmitOrderStep.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/SubmitOrderStep.php
@@ -66,16 +66,16 @@ class SubmitOrderStep implements TestStepInterface
      * @param SalesOrderView $salesOrderView
      * @param FixtureFactory $fixtureFactory
      * @param Customer $customer
-     * @param Address $billingAddress
      * @param \Magento\Mtf\Fixture\FixtureInterface[] $products
+     * @param Address|null $billingAddress
      */
     public function __construct(
         OrderCreateIndex $orderCreateIndex,
         SalesOrderView $salesOrderView,
         FixtureFactory $fixtureFactory,
         Customer $customer,
-        Address $billingAddress,
-        array $products
+        array $products,
+        Address $billingAddress = null
     ) {
         $this->orderCreateIndex = $orderCreateIndex;
         $this->salesOrderView = $salesOrderView;
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/etc/di.xml
index 157dfc0f77302318bdce435dd3af7f6de5e261fb..e9670a1d727f72b2d7ea853fd38e4b0a2bb1c218 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/etc/di.xml
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/etc/di.xml
@@ -106,4 +106,9 @@
             <argument name="severity" xsi:type="string">S1</argument>
         </arguments>
     </type>
+    <type name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCanceled">
+        <arguments>
+            <argument name="severity" xsi:type="string">S0</argument>
+        </arguments>
+    </type>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml
index 030b0f4f32df0eacd76c99cbe55537df1c734cf5..fa4329137b0272a5ae59cefdf217baa894c2cd28 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml
@@ -86,4 +86,33 @@
         <step name="submitOrder" module="Magento_Sales" next="createInvoice" />
         <step name="createInvoice" module="Magento_Sales" />
     </scenario>
+    <scenario name="CreateOnlineCreditMemoTest" 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="createCustomer" />
+        <step name="createCustomer" module="Magento_Customer" next="proceedToCheckout" />
+        <step name="proceedToCheckout" module="Magento_Checkout" next="selectCheckoutMethod" />
+        <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress" />
+        <step name="fillShippingAddress" module="Magento_Checkout" next="fillShippingMethod" />
+        <step name="fillShippingMethod" module="Magento_Checkout" next="selectPaymentMethod" />
+        <step name="selectPaymentMethod" module="Magento_Checkout" next="placeOrder" />
+        <step name="placeOrder" module="Magento_Checkout" next="createInvoice" />
+        <step name="createInvoice" module="Magento_Sales" next="createOnlineCreditMemo" />
+        <step name="createOnlineCreditMemo" module="Magento_Sales" />
+    </scenario>
+    <scenario name="CloseOrderTest" firstStep="setupConfiguration">
+        <step name="setupConfiguration" module="Magento_Config" next="createProducts" />
+        <step name="createProducts" module="Magento_Catalog" next="createTaxRule" />
+        <step name="createTaxRule" module="Magento_Tax" next="addProductsToTheCart" />
+        <step name="addProductsToTheCart" module="Magento_Checkout" next="proceedToCheckout" />
+        <step name="proceedToCheckout" module="Magento_Checkout" next="createCustomer" />
+        <step name="createCustomer" module="Magento_Customer" next="selectCheckoutMethod" />
+        <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress"/>
+        <step name="fillShippingAddress" module="Magento_Checkout" next="fillShippingMethod" />
+        <step name="fillShippingMethod" module="Magento_Checkout" next="selectPaymentMethod" />
+        <step name="selectPaymentMethod" module="Magento_Checkout" next="placeOrder" />
+        <step name="placeOrder" module="Magento_Checkout" next="createInvoice" />
+        <step name="createInvoice" module="Magento_Sales" next="createShipment" />
+        <step name="createShipment" module="Magento_Sales" />
+    </scenario>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.php
index 7e0204a90d4e177e4eaad066cdeb9b3c6df702e4..a435334e7a76c724027f467d76d68eca34780f2d 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.php
@@ -9,11 +9,13 @@ namespace Magento\SalesRule\Test\TestCase;
 use Magento\SalesRule\Test\Fixture\SalesRule;
 use Magento\SalesRule\Test\Page\Adminhtml\PromoQuoteEdit;
 use Magento\SalesRule\Test\Page\Adminhtml\PromoQuoteIndex;
+use Magento\Catalog\Test\Fixture\CatalogProductSimple;
 use Magento\Mtf\TestCase\Injectable;
 
 /**
  * Precondition:
  * 1. Several Cart Price Rules are created.
+ * 2. Create sales rule from dataset using Handler.
  *
  * Steps:
  * 1. Login to backend.
@@ -63,13 +65,18 @@ class DeleteSalesRuleEntityTest extends Injectable
      * Delete Sales Rule Entity.
      *
      * @param SalesRule $salesRule
+     * @param CatalogProductSimple $productForSalesRule1
      * @return void
      */
-    public function testDeleteSalesRule(SalesRule $salesRule)
+    public function test(SalesRule $salesRule, CatalogProductSimple $productForSalesRule1 = null)
     {
         // Preconditions
         $salesRule->persist();
 
+        if ($productForSalesRule1) {
+            $productForSalesRule1->persist();
+        }
+
         // Steps
         $this->promoQuoteIndex->open();
         $this->promoQuoteIndex->getPromoQuoteGrid()->searchAndOpen(['name' => $salesRule->getName()]);
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.xml
index 80dafe5b30181ce2b1635d8ddaecf609b88bb891..14c325c309e263d18d5edc3998c2fc7dfd6d2a67 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/DeleteSalesRuleEntityTest.xml
@@ -17,10 +17,13 @@
             <constraint name="Magento\SalesRule\Test\Constraint\AssertCartPriceRuleSuccessDeleteMessage" />
             <constraint name="Magento\SalesRule\Test\Constraint\AssertCartPriceRuleIsNotPresentedInGrid" />
         </variation>
-        <variation name="DeleteSalesRuleEntityTestVariation3">
+        <variation name="DeleteSalesRuleEntityTestVariation3" summary="Assert That Cart Price Rule Condition Is Not Applied" ticketId="MAGETWO-16987">
             <data name="salesRule/dataset" xsi:type="string">inactive_sales_rule</data>
+            <data name="productForSalesRule1/dataset" xsi:type="string">simple_for_salesrule_1</data>
+            <data name="productQuantity/productForSalesRule1" xsi:type="string">1</data>
             <constraint name="Magento\SalesRule\Test\Constraint\AssertCartPriceRuleSuccessDeleteMessage" />
             <constraint name="Magento\SalesRule\Test\Constraint\AssertCartPriceRuleIsNotPresentedInGrid" />
+            <constraint name="Magento\SalesRule\Test\Constraint\AssertCartPriceRuleConditionIsNotApplied" />
         </variation>
     </testCase>
 </config>
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
index 7391d2281f8094b059cfaf9d26115c371d9498b0..3cfbf45c0ea8b231233608da21e64f9ce4fc2b24 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ShoppingCartWithFreeShippingTest.xml
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ShoppingCartWithFreeShippingTest.xml
@@ -16,7 +16,7 @@
         </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="product/dataset" xsi:type="string">simple_with_weight_10</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>
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/Constraint/AssertSynonymRestrictedAccess.php b/dev/tests/functional/tests/app/Magento/Search/Test/Constraint/AssertSynonymRestrictedAccess.php
new file mode 100644
index 0000000000000000000000000000000000000000..2153f80fec9a50aa2007045be609e2c8e2aa11b0
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/Constraint/AssertSynonymRestrictedAccess.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Search\Test\Constraint;
+
+use Magento\Search\Test\Page\Adminhtml\SynonymGroupIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Backend\Test\Page\Adminhtml\Dashboard;
+
+/**
+ * Assert that access to synonym group index page by direct url is restricted.
+ */
+class AssertSynonymRestrictedAccess extends AbstractConstraint
+{
+    /**
+     * Access denied text.
+     */
+    const ACCESS_DENIED_TEXT = 'Access denied';
+
+    /**
+     * Assert that access to synonym group index page is restricted.
+     *
+     * @param Dashboard $dashboard
+     * @param SynonymGroupIndex $synonymGroupIndex
+     * @return void
+     */
+    public function processAssert(Dashboard $dashboard, SynonymGroupIndex $synonymGroupIndex)
+    {
+        $synonymGroupIndex->open();
+
+        \PHPUnit_Framework_Assert::assertContains(
+            self::ACCESS_DENIED_TEXT,
+            $dashboard->getErrorBlock()->getContent(),
+            'Synonym group index page is available.'
+        );
+    }
+
+    /**
+     * Returns a string representation of successful assertion.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Access to synonym group index page by direct url is restricted.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/AdvancedSearchWithAttributeTest.php b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/AdvancedSearchWithAttributeTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..35d1bd033a0b91e9cd12ae5aed655f0de4983a5b
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/AdvancedSearchWithAttributeTest.php
@@ -0,0 +1,391 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Search\Test\TestCase;
+
+use Magento\Indexer\Test\Constraint\AssertUpdateByScheduleSuccessSaveMessage as AssertSuccessSaveMessage;
+use Magento\CatalogSearch\Test\Page\AdvancedSearch;
+use Magento\Indexer\Test\Page\Adminhtml\IndexManagement;
+use Magento\Mtf\TestCase\Injectable;
+use Magento\Mtf\Util\Command\Cli\Indexer;
+use Magento\CatalogSearch\Test\Constraint\AssertSearchAttributeTest;
+use Magento\Indexer\Test\Constraint\AssertIndexerStatus;
+use Magento\Catalog\Test\Constraint\AssertProductAttributeSaveMessage;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductAttributeIndex;
+use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductAttributeNew;
+use Magento\CatalogSearch\Test\Page\AdvancedResult;
+use Magento\CatalogSearch\Test\Constraint\AssertAdvancedSearchProductResult;
+use Magento\Catalog\Test\Constraint\AssertProductSaveMessage;
+use Magento\Catalog\Test\Fixture\CatalogProductAttribute;
+use Magento\Catalog\Test\Fixture\CatalogProductSimple;
+use Magento\Catalog\Test\Fixture\Category;
+
+/**
+ * Preconditions:
+ * 1. Backend -> System -> New Index Management
+ * 2. Product EAV = Update by Schedule
+ *      Cron is turned off.
+ * 3. Perform full reindex: "bin/magento indexer:reindex".
+ * Steps:
+ * 1. Call assert to check index status (Product EAV indexer: Status = Ready)
+ * 2. Open Backend -> Stores -> Attributes -> Product
+ * 3. Open Weight attribute
+ * 4. Update and save attribute to:
+ *      Use in Advanced Search = Yes
+ * 5. Call assert to check index status (Product EAV indexer: Status = Required Reindex)
+ * 6. Assert that weight attribute is available on the Advanced Search
+ * 7. Run Full reindex from console
+ * 8. Change Weight attribute and save
+ *      Scope = Website (Advanced Attribute Properties)
+ * 10. Call assert to check index status (Product EAV indexer: Status = Required Reindex)
+ * 11. Assert that weight attribute is available on the Advanced Search
+ * 12. Run Full reindex from console
+ * 13. Create simple product with default attribute set with weight = 1
+ * 14. Create grouped product so that it will include simple product as option
+ * 15. Create bundle product so that it will include simple product as option
+ * 16. Create configurable product with one option product for which weight = 2
+ * 17. Call assert to check index status (Product EAV indexer: Status = Ready
+ * 18. Open Advanced Search on frontend
+ * 19. Enter value to Weight = 1 and click Search button
+ * 20. Assert that page with 3 products is open:
+ *      Simple
+ *      Bundle
+ *      Grouped
+ * 21. Update Weight Attribute in Backend
+ *      Use in Advanced Search = No
+ * 22. Call assert to check index status (Product EAV indexer: Status = Required Reindex)
+ * 23. Assert that weight attribute is absent the Advanced Search
+ * 24. Run Full reindex from console
+ *
+ * @group Search
+ * @ZephyrId MAGETWO-25931
+ * @SuppressWarnings(PHPMD.TooManyFields)
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class AdvancedSearchWithAttributeTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    /* end tags */
+
+    /**
+     * Assert that Attribute is present in Advanced Search Page.
+     *
+     * @var AssertSearchAttributeTest
+     */
+    private $assertSearchAttributeTest;
+
+    /**
+     * Products for search
+     *
+     * @var array
+     */
+    private $products;
+
+    /**
+     * Attribute for check in Advanced Search Page.
+     *
+     * @var string
+     */
+    private $attributeForSearch;
+
+    /**
+     * Default weight attribute value.
+     *
+     * @var CatalogProductAttribute
+     */
+    private $attributeDisable;
+
+    /**
+     * Indexers in Index Management Page.
+     *
+     * @var array
+     */
+    private $indexers;
+
+    /**
+     * Advanced Search Page.
+     *
+     * @var AdvancedSearch
+     */
+    private $advancedSearch;
+
+    /**
+     * Index Management Page.
+     *
+     * @var IndexManagement
+     */
+    private $indexManagement;
+
+    /**
+     * Perform bin/magento commands from command line for functional tests executions.
+     *
+     * @var Indexer
+     */
+    private $cli;
+
+    /**
+     * Advanced Result Page.
+     *
+     * @var ResultPage
+     */
+    private $resultPage;
+
+    /**
+     * Catalog Product Index Page.
+     *
+     * @var ProductGrid
+     */
+    private $productGrid;
+
+    /**
+     * Catalog Product New Page.
+     *
+     * @var NewProductPage
+     */
+    private $newProductPage;
+
+    /**
+     * Catalog Product Edit Page.
+     *
+     * @var ProductEdit
+     */
+    private $productEdit;
+
+    /**
+     * Catalog Product Attribute New Page.
+     *
+     * @var AttributeNewPage
+     */
+    private $attributeNewPage;
+
+    /**
+     * Assert Indexer Status.
+     *
+     * @var AssertIndexerStatus
+     */
+    private $assertIndexerStatus;
+
+    /**
+     * Assert Creation Product.
+     *
+     * @var AssertProductSaveMessage
+     */
+    private $assertCreateProducts;
+
+    /**
+     * Assert Creation Product.
+     *
+     * @var CatalogProductAttributeIndex
+     */
+    private $productAttributePage;
+
+    /**
+     * Assert Success Message Indexer Update by Schedule.
+     *
+     * @var AssertSuccessSaveMessage
+     */
+    private $assertSuccessSaveMessage;
+
+    /**
+     * Assert Success Message is Present After Save Attribute.
+     *
+     * @var AssertAdvancedSearchResult
+     */
+    private $assertAdvancedSearchResult;
+
+    /**
+     * Assert Products in Advanced Search Result Page.
+     *
+     * @var AssertAttributeStatus
+     */
+    private $assertAttributeStatus;
+
+    /**
+     * Inject pages.
+     *
+     * @param IndexManagement $indexManagement
+     * @param AdvancedSearch $advancedSearch
+     * @param AdvancedResult $resultPage
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductNew $newProductPage
+     * @param CatalogProductEdit $productEdit
+     * @param AssertIndexerStatus $assertIndexerStatus
+     * @param AssertProductSaveMessage $assertCreateProducts
+     * @param CatalogProductAttributeIndex $productAttributePage
+     * @param CatalogProductAttributeNew $attributeNewPage
+     * @param AssertSuccessSaveMessage $assertSuccessSaveMessage
+     * @param AssertSearchAttributeTest $assertSearchAttributeTest
+     * @param AssertAdvancedSearchProductResult $assertAdvancedSearchResult
+     * @param AssertProductAttributeSaveMessage $assertAttributeStatus
+     * @return void
+     * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
+     */
+    public function __inject(
+        IndexManagement $indexManagement,
+        AdvancedSearch $advancedSearch,
+        AdvancedResult $resultPage,
+        CatalogProductIndex $productGrid,
+        CatalogProductNew $newProductPage,
+        CatalogProductEdit $productEdit,
+        AssertIndexerStatus $assertIndexerStatus,
+        AssertProductSaveMessage $assertCreateProducts,
+        CatalogProductAttributeIndex $productAttributePage,
+        CatalogProductAttributeNew $attributeNewPage,
+        AssertSuccessSaveMessage $assertSuccessSaveMessage,
+        AssertSearchAttributeTest $assertSearchAttributeTest,
+        AssertAdvancedSearchProductResult $assertAdvancedSearchResult,
+        AssertProductAttributeSaveMessage $assertAttributeStatus
+    ) {
+        $this->indexManagement = $indexManagement;
+        $this->advancedSearch = $advancedSearch;
+        $this->resultPage = $resultPage;
+        $this->productGrid = $productGrid;
+        $this->newProductPage = $newProductPage;
+        $this->productEdit = $productEdit;
+        $this->assertIndexerStatus = $assertIndexerStatus;
+        $this->assertCreateProducts = $assertCreateProducts;
+        $this->productAttributePage = $productAttributePage;
+        $this->attributeNewPage = $attributeNewPage;
+        $this->assertSuccessSaveMessage = $assertSuccessSaveMessage;
+        $this->assertSearchAttributeTest = $assertSearchAttributeTest;
+        $this->assertAdvancedSearchResult = $assertAdvancedSearchResult;
+        $this->assertAttributeStatus = $assertAttributeStatus;
+    }
+
+    /**
+     * Use Advanced Search by Decimal indexable attribute if Edit/Add Attribute.
+     *
+     * @param Indexer $cli
+     * @param Category $category
+     * @param FixtureFactory $fixtureFactory
+     * @param CatalogProductSimple $productSearch
+     * @param CatalogProductAttribute $attributeEnable
+     * @param CatalogProductAttribute $attributeDisable
+     * @param CatalogProductAttribute $attributeGlobalStatus
+     * @param string $attributeForSearch
+     * @param array $isVisibleInAdvancedSearch
+     * @param array $productDropDownList
+     * @param array $products
+     * @param string|null $indexers
+     * @return void
+     * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
+     */
+    public function test(
+        Indexer $cli,
+        Category $category,
+        FixtureFactory $fixtureFactory,
+        CatalogProductSimple $productSearch,
+        CatalogProductAttribute $attributeEnable,
+        CatalogProductAttribute $attributeDisable,
+        CatalogProductAttribute $attributeGlobalStatus,
+        $attributeForSearch,
+        array $isVisibleInAdvancedSearch,
+        array $productDropDownList,
+        array $products,
+        $indexers = null
+    ) {
+        $this->cli = $cli;
+        $this->products = $products;
+        $this->attributeDisable = $attributeDisable;
+        $this->attributeForSearch = $attributeForSearch;
+        $this->indexers = explode(',', $indexers);
+
+        $category->persist();
+
+        // Indexers Update bu Schedule
+        $this->indexManagement->open();
+        $this->indexManagement->getMainBlock()->updateBySchedule($this->indexers);
+        //Assert attribute Update by Schedule
+        $this->assertSuccessSaveMessage->processAssert($this->indexManagement, $this->indexers);
+
+        // Full indexers reindex
+        $cli->reindex();
+        // Assert indexers status
+        $this->assertIndexerStatus->processAssert($this->indexManagement, $this->indexers);
+        $this->productAttributePage->open();
+        $this->productAttributePage->getGrid()->searchAndOpen(['attribute_code' => $attributeForSearch['name']]);
+        $this->attributeNewPage->getAttributeForm()->fill($attributeEnable);
+        $this->attributeNewPage->getPageActions()->save();
+        // Assert attribute status
+        $this->assertAttributeStatus->processAssert($this->productAttributePage);
+
+        // Assert indexers status
+        $this->assertIndexerStatus->processAssert($this->indexManagement, $this->indexers, false);
+
+        $this->assertSearchAttributeTest->processAssert($this->advancedSearch, $attributeForSearch);
+        $cli->reindex();
+
+        // Change attribute 'scope mode'
+        $this->productAttributePage->open();
+        $this->productAttributePage->getGrid()->searchAndOpen(['attribute_code' => $attributeForSearch['name']]);
+        $this->attributeNewPage->getAttributeForm()->fill($attributeGlobalStatus);
+        $this->attributeNewPage->getPageActions()->save();
+        // Assert attribute status
+        $this->assertAttributeStatus->processAssert($this->productAttributePage);
+
+        // Assert indexers status
+        $this->assertIndexerStatus->processAssert($this->indexManagement, $this->indexers, false);
+
+        // Assert advanced attribute is present(or absent) in Advanced Search Page.
+        $this->assertSearchAttributeTest->processAssert($this->advancedSearch, $attributeForSearch);
+        $cli->reindex();
+
+        // Create Products
+        $allProducts = [];
+        foreach ($products as $key => $product) {
+            list($fixtureCode, $dataset) = explode('::', $product);
+            $this->productGrid->open();
+            $this->productGrid->getGridPageActionBlock()->addProduct($productDropDownList[$key]);
+            $product = $fixtureFactory->createByCode($fixtureCode, ['dataset' => $dataset]);
+            $this->newProductPage->getProductForm()->fill($product, null, $category);
+            $this->newProductPage->getFormPageActions()->save($product);
+
+            $this->assertCreateProducts->processAssert($this->productEdit);
+            $allProducts[] = $product;
+        }
+
+        $cli->reindex();
+        $this->advancedSearch->open();
+        $this->advancedSearch->getForm()->fill($productSearch)->submit();
+
+        // Assert that Advanced Search result page contains only product(s) according to requested from fixture
+        $this->assertAdvancedSearchResult->processAssert($isVisibleInAdvancedSearch, $allProducts, $this->resultPage);
+        $this->productAttributePage->open();
+        $this->productAttributePage->getGrid()->searchAndOpen(['attribute_code' => $this->attributeForSearch['name']]);
+        $this->attributeNewPage->getAttributeForm()->fill($this->attributeDisable);
+        $this->attributeNewPage->getPageActions()->save();
+        // Assert attribute status
+        $this->assertAttributeStatus->processAssert($this->productAttributePage);
+
+        $this->assertIndexerStatus->processAssert($this->indexManagement, $this->indexers, false);
+        $cli->reindex();
+        unset($this->attributeForSearch['isVisible']);
+        $this->assertSearchAttributeTest->processAssert($this->advancedSearch, $this->attributeForSearch);
+    }
+
+    /**
+     * Set attribute default value.
+     *
+     * @return void
+     */
+    protected function tearDown()
+    {
+        $this->productAttributePage->open();
+        $this->productAttributePage->getGrid()->searchAndOpen(['attribute_code' => $this->attributeForSearch['name']]);
+        $this->attributeNewPage->getAttributeForm()->fill($this->attributeDisable);
+        $this->attributeNewPage->getPageActions()->save();
+        $this->indexManagement->open();
+        $this->indexManagement->getMainBlock()->massaction([], 'Update on Save', false, 'Select All');
+        $this->cli->reindex();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/AdvancedSearchWithAttributeTest.xml b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/AdvancedSearchWithAttributeTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..930818fcb5ccd14f7ad22464f29179789af49ffd
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/AdvancedSearchWithAttributeTest.xml
@@ -0,0 +1,38 @@
+<?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\Search\Test\TestCase\AdvancedSearchWithAttributeTest" summary="Use Advanced Search by Decimal indexable attribute if Edit/Add Attribute" ticketId="MAGETWO-25931">
+        <variation name="AdvancedSearchWithWeightAttributeTestVariation1">
+            <data name="productDropDownList/0" xsi:type="string">configurable</data>
+            <data name="productDropDownList/1" xsi:type="string">simple</data>
+            <data name="productDropDownList/2" xsi:type="string">bundle</data>
+            <data name="productDropDownList/3" xsi:type="string">grouped</data>
+            <data name="isVisibleInAdvancedSearch/0" xsi:type="string">No</data>
+            <data name="isVisibleInAdvancedSearch/1" xsi:type="string">Yes</data>
+            <data name="isVisibleInAdvancedSearch/2" xsi:type="string">Yes</data>
+            <data name="isVisibleInAdvancedSearch/3" xsi:type="string">Yes</data>
+            <data name="attributeEnable/data/is_searchable" xsi:type="string">Yes</data>
+            <data name="attributeEnable/data/is_visible_in_advanced_search" xsi:type="string">Yes</data>
+            <data name="attributeDisable/data/is_global" xsi:type="string">Global</data>
+            <data name="attributeDisable/data/is_searchable" xsi:type="string">No</data>
+            <data name="attributeGlobalStatus/data/is_global" xsi:type="string">Website</data>
+            <data name="products/0" xsi:type="string">configurableProduct::one_simple_product</data>
+            <data name="products/1" xsi:type="string">catalogProductSimple::default</data>
+            <data name="products/2" xsi:type="string">bundleProduct::default_with_one_simple_product</data>
+            <data name="products/3" xsi:type="string">groupedProduct::withSimpleProduct_without_category</data>
+            <data name="productSearch/data/additional_attributes/weight_from" xsi:type="string">1</data>
+            <data name="productSearch/data/additional_attributes/weight_to" xsi:type="string">1</data>
+            <data name="indexers" xsi:type="string">Product EAV</data>
+            <data name="attributeForSearch" xsi:type="array">
+                <item name="name" xsi:type="string">Weight</item>
+                <item name="isVisible" xsi:type="boolean">true</item>
+            </data>
+            <data name="product/data/category" xsi:type="string">category_%isolation%</data>
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/CustomAclPermissionTest.xml b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/CustomAclPermissionTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d09025d4f4ef35b32539bc918c3dda385ded5535
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/CustomAclPermissionTest.xml
@@ -0,0 +1,17 @@
+<?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\User\Test\TestCase\CustomAclPermissionTest" summary="Custom ACL Permission" ticketId="MAGETWO-58541">
+        <variation name="CustomSynonymAclPermissionTestVariation2" summary="Global synonyms grid access control" ticketId="MAGETWO-47568">
+            <data name="user/dataset" xsi:type="string">custom_admin_with_role_without_synonym</data>
+            <data name="menuItem" xsi:type="string">Marketing > Search Synonyms</data>
+            <constraint name="Magento\Backend\Test\Constraint\AssertMenuItemNotVisible" />
+            <constraint name="Magento\Search\Test\Constraint\AssertSynonymRestrictedAccess" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertCustomerPasswordRequiredClasses.php b/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertCustomerPasswordRequiredClasses.php
new file mode 100644
index 0000000000000000000000000000000000000000..272a98cb298eba58d4d858ec35500924e8b6db27
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Security/Test/Constraint/AssertCustomerPasswordRequiredClasses.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Security\Test\Constraint;
+
+use Magento\Customer\Test\Page\CustomerAccountCreate;
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Config\Test\Fixture\ConfigData;
+
+/**
+ * Assert error message is displayed after customer enter password.
+ */
+class AssertCustomerPasswordRequiredClasses extends AbstractConstraint
+{
+    const EXPECTED_MAX_CHARACTERS = 'Minimum of different classes of characters in password is %s.';
+    const EXPECTED_MESSAGE = ' Classes of characters: Lower Case, Upper Case, Digits, Special Characters.';
+
+    /**
+     * Assert error message is displayed after customer enter password.
+     *
+     * @param CustomerAccountCreate $registerPage
+     * @param ConfigData $config
+     * @return void
+     */
+    public function processAssert(CustomerAccountCreate $registerPage, ConfigData $config)
+    {
+        $errorMessage = $registerPage->getRegisterForm()->getPasswordError();
+        $characterClassesNumber = $config
+            ->getData('section')['customer/password/required_character_classes_number']['value'];
+
+        \PHPUnit_Framework_Assert::assertEquals(
+            sprintf(self::EXPECTED_MAX_CHARACTERS, $characterClassesNumber) . self::EXPECTED_MESSAGE,
+            $errorMessage,
+            'Wrong expected message is displayed.'
+            . "\nExpected: " . sprintf(self::EXPECTED_MAX_CHARACTERS, $characterClassesNumber) . self::EXPECTED_MESSAGE
+            . "\nActual: " . $errorMessage
+        );
+    }
+
+    /**
+     * Text of success register message is displayed.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return "Customer's password is not correct.";
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Security/Test/Repository/ConfigData.xml
index 8369c43b91a1a87e06c69489985931fb4e97182b..0e65237595ce4b87832b95b0113d7cc0f5cdc0f6 100644
--- a/dev/tests/functional/tests/app/Magento/Security/Test/Repository/ConfigData.xml
+++ b/dev/tests/functional/tests/app/Magento/Security/Test/Repository/ConfigData.xml
@@ -23,6 +23,14 @@
                 <item name="value" xsi:type="string">10</item>
             </field>
         </dataset>
+        <dataset name="default_required_character_classes_number">
+            <field name="customer/password/required_character_classes_number" xsi:type="array">
+                <item name="scope" xsi:type="string">customer</item>
+                <item name="scope_id" xsi:type="number">1</item>
+                <item name="label" xsi:type="string">10</item>
+                <item name="value" xsi:type="string">3</item>
+            </field>
+        </dataset>
         <dataset name="user_lockout_failures">
             <field name="admin/security/lockout_failures" xsi:type="array">
                 <item name="scope" xsi:type="string">admin</item>
diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/RegisterCustomerEntityWithDifferentPasswordClassesTest.php b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/RegisterCustomerEntityWithDifferentPasswordClassesTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..94b12d6c78b112a27d7d839a47b051c2b83a4b81
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/RegisterCustomerEntityWithDifferentPasswordClassesTest.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Security\Test\TestCase;
+
+use Magento\Customer\Test\Fixture\Customer;
+use Magento\Customer\Test\Page\CustomerAccountCreate;
+use Magento\Cms\Test\Page\CmsIndex;
+use Magento\Mtf\TestCase\Injectable;
+use Magento\Mtf\TestStep\TestStepFactory;
+use Magento\Config\Test\Fixture\ConfigData;
+
+/**
+ * Test Flow:
+ * 1. Go to frontend.
+ * 2. Click Register link.
+ * 3. Fill registry form.
+ * 4. Click 'Create account' button.
+ * 5. Perform assertions.
+ *
+ * @ZephyrId MAGETWO-49045
+ */
+class RegisterCustomerEntityWithDifferentPasswordClassesTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    const SEVERITY = 'S1';
+    /* end tags */
+
+    /**
+     * Customer registry page.
+     *
+     * @var CustomerAccountCreate
+     */
+    protected $customerAccountCreate;
+
+    /**
+     * Cms page.
+     *
+     * @var CmsIndex $cmsIndex
+     */
+    protected $cmsIndex;
+
+    /**
+     * Test step factory.
+     *
+     * @var TestStepFactory
+     */
+    protected $testStepFactory;
+
+    /**
+     * Inject data.
+     *
+     * @param CustomerAccountCreate $customerAccountCreate
+     * @param CmsIndex $cmsIndex
+     * @param TestStepFactory $testStepFactory
+     * @return void
+     */
+    public function __inject(
+        CustomerAccountCreate $customerAccountCreate,
+        CmsIndex $cmsIndex,
+        TestStepFactory $testStepFactory
+    ) {
+        $this->customerAccountCreate = $customerAccountCreate;
+        $this->cmsIndex = $cmsIndex;
+        $this->testStepFactory = $testStepFactory;
+    }
+
+    /**
+     * Create Customer account on Storefront.
+     *
+     * @param Customer $customer
+     * @param ConfigData $config
+     * @return void
+     */
+    public function test(Customer $customer, ConfigData $config)
+    {
+        // Preconditions
+        $config->persist();
+        // Steps
+        $this->cmsIndex->open();
+        $this->cmsIndex->getLinksBlock()->openLink('Create an Account');
+        $this->customerAccountCreate->getRegisterForm()->registerCustomer($customer);
+
+        $characterClassesNumber = $config
+            ->getData('section')['customer/password/required_character_classes_number']['value'];
+
+        return ['characterClassesNumber' => $characterClassesNumber];
+    }
+
+    /**
+     * Set default settings and logout customer.
+     *
+     * @return void
+     */
+    protected function tearDown()
+    {
+        //Set default required character classes for the password
+        $this->objectManager->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => 'default_required_character_classes_number']
+        )->run();
+        // Logout customer
+        $this->testStepFactory->create(
+            \Magento\Customer\Test\TestStep\LogoutCustomerOnFrontendStep::class
+        )->run();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/RegisterCustomerEntityWithDifferentPasswordClassesTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/RegisterCustomerEntityWithDifferentPasswordClassesTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e11ed99dd8e3ec355ab84f4af8a1f7223af2c101
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/RegisterCustomerEntityWithDifferentPasswordClassesTest.xml
@@ -0,0 +1,95 @@
+<?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\Security\Test\TestCase\RegisterCustomerEntityWithDifferentPasswordClassesTest" summary="Register customer with different required character classes for the password" ticketId="MAGETWO-49045">
+        <variation name="RegisterCustomerEntityWithDifferentPasswordClassesVariation1">
+            <data name="config/dataset" xsi:type="string">default_required_character_classes_number</data>
+            <data name="config/data" xsi:type="array">
+                <item name="customer/password/required_character_classes_number" xsi:type="array">
+                    <item name="value" xsi:type="string">1</item>
+                </item>
+            </data>
+            <data name="customer/dataset" xsi:type="string">register_customer</data>
+            <data name="customer/data/password" xsi:type="string">12345678</data>
+            <data name="customer/data/password_confirmation" xsi:type="string">12345678</data>
+            <constraint name="Magento\Customer\Test\Constraint\AssertCustomerSuccessRegisterMessage" />
+        </variation>
+        <variation name="RegisterCustomerEntityWithDifferentPasswordClassesVariation2">
+            <data name="config/dataset" xsi:type="string">default_required_character_classes_number</data>
+            <data name="config/data" xsi:type="array">
+                <item name="customer/password/required_character_classes_number" xsi:type="array">
+                    <item name="value" xsi:type="string">2</item>
+                </item>
+            </data>
+            <data name="customer/dataset" xsi:type="string">register_customer</data>
+            <data name="customer/data/password" xsi:type="string">abc12345</data>
+            <data name="customer/data/password_confirmation" xsi:type="string">abc12345</data>
+            <constraint name="Magento\Customer\Test\Constraint\AssertCustomerSuccessRegisterMessage" />
+        </variation>
+        <variation name="RegisterCustomerEntityWithDifferentPasswordClassesVariation3">
+            <data name="config/dataset" xsi:type="string">default_required_character_classes_number</data>
+            <data name="config/data" xsi:type="array">
+                <item name="customer/password/required_character_classes_number" xsi:type="array">
+                    <item name="value" xsi:type="string">2</item>
+                </item>
+            </data>
+            <data name="customer/dataset" xsi:type="string">register_customer</data>
+            <data name="customer/data/password" xsi:type="string">12345678</data>
+            <data name="customer/data/password_confirmation" xsi:type="string">12345678</data>
+            <constraint name="Magento\Security\Test\Constraint\AssertCustomerPasswordRequiredClasses" />
+        </variation>
+        <variation name="RegisterCustomerEntityWithDifferentPasswordClassesVariation4">
+            <data name="config/dataset" xsi:type="string">default_required_character_classes_number</data>
+            <data name="config/data" xsi:type="array">
+                <item name="customer/password/required_character_classes_number" xsi:type="array">
+                    <item name="value" xsi:type="string">3</item>
+                </item>
+            </data>
+            <data name="customer/dataset" xsi:type="string">register_customer</data>
+            <data name="customer/data/password" xsi:type="string">abcXYZ123</data>
+            <data name="customer/data/password_confirmation" xsi:type="string">abcXYZ123</data>
+            <constraint name="Magento\Customer\Test\Constraint\AssertCustomerSuccessRegisterMessage" />
+        </variation>
+        <variation name="RegisterCustomerEntityWithDifferentPasswordClassesVariation5">
+            <data name="config/dataset" xsi:type="string">default_required_character_classes_number</data>
+            <data name="config/data" xsi:type="array">
+                <item name="customer/password/required_character_classes_number" xsi:type="array">
+                    <item name="value" xsi:type="string">3</item>
+                </item>
+            </data>
+            <data name="customer/dataset" xsi:type="string">register_customer</data>
+            <data name="customer/data/password" xsi:type="string">abc12345</data>
+            <data name="customer/data/password_confirmation" xsi:type="string">abc12345</data>
+            <constraint name="Magento\Security\Test\Constraint\AssertCustomerPasswordRequiredClasses" />
+        </variation>
+        <variation name="RegisterCustomerEntityWithDifferentPasswordClassesVariation6">
+            <data name="config/dataset" xsi:type="string">default_required_character_classes_number</data>
+            <data name="config/data" xsi:type="array">
+                <item name="customer/password/required_character_classes_number" xsi:type="array">
+                    <item name="value" xsi:type="string">4</item>
+                </item>
+            </data>
+            <data name="customer/dataset" xsi:type="string">register_customer</data>
+            <data name="customer/data/password" xsi:type="string">abcXYZ12^</data>
+            <data name="customer/data/password_confirmation" xsi:type="string">abcXYZ12^</data>
+            <constraint name="Magento\Customer\Test\Constraint\AssertCustomerSuccessRegisterMessage" />
+        </variation>
+        <variation name="RegisterCustomerEntityWithDifferentPasswordClassesVariation7">
+            <data name="config/dataset" xsi:type="string">default_required_character_classes_number</data>
+            <data name="config/data" xsi:type="array">
+                <item name="customer/password/required_character_classes_number" xsi:type="array">
+                    <item name="value" xsi:type="string">4</item>
+                </item>
+            </data>
+            <data name="customer/dataset" xsi:type="string">register_customer</data>
+            <data name="customer/data/password" xsi:type="string">abcXYZ123</data>
+            <data name="customer/data/password_confirmation" xsi:type="string">abcXYZ123</data>
+            <constraint name="Magento\Security\Test\Constraint\AssertCustomerPasswordRequiredClasses" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Shipping/Test/Block/Adminhtml/Shipment/Grid.php b/dev/tests/functional/tests/app/Magento/Shipping/Test/Block/Adminhtml/Shipment/Grid.php
index d3bd91eddc735b2138b45d4f6b3476cfad34d656..0eccfe7af2929865c41173d6765ffca400e896ff 100644
--- a/dev/tests/functional/tests/app/Magento/Shipping/Test/Block/Adminhtml/Shipment/Grid.php
+++ b/dev/tests/functional/tests/app/Magento/Shipping/Test/Block/Adminhtml/Shipment/Grid.php
@@ -33,10 +33,10 @@ class Grid extends GridInterface
             'selector' => 'input[name="order_increment_id"]',
         ],
         'total_qty_from' => [
-            'selector' => 'input[name="total_qty[from]"',
+            'selector' => 'input[name="total_qty[from]"]',
         ],
         'total_qty_to' => [
-            'selector' => 'input[name="total_qty][to]"',
+            'selector' => 'input[name="total_qty[to]"]',
         ],
     ];
 }
diff --git a/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertShipmentInShipmentsTab.php b/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertShipmentInShipmentsTab.php
index ad4a73f1036d12688891e862c540507e3abf4678..d01ebe62432f142ef79722a1d15d61de4445cfb2 100644
--- a/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertShipmentInShipmentsTab.php
+++ b/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertShipmentInShipmentsTab.php
@@ -44,7 +44,11 @@ class AssertShipmentInShipmentsTab extends AbstractConstraint
                 'qty_to' => $totalQty[$key],
             ];
             \PHPUnit_Framework_Assert::assertTrue(
-                $salesOrderView->getOrderForm()->getTab('shipments')->getGridBlock()->isRowVisible($filter),
+                $salesOrderView
+                    ->getOrderForm()
+                    ->getTab('shipments')
+                    ->getGridBlock()
+                    ->isRowVisible($filter, true, false),
                 'Shipment is absent on shipments tab.'
             );
         }
diff --git a/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertShipmentNotInShipmentsGrid.php b/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertShipmentNotInShipmentsGrid.php
new file mode 100644
index 0000000000000000000000000000000000000000..c46130907ac5d8ab63228731c8e0c897f45edd37
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertShipmentNotInShipmentsGrid.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Shipping\Test\Constraint;
+
+use Magento\Sales\Test\Fixture\OrderInjectable;
+use Magento\Shipping\Test\Page\Adminhtml\ShipmentIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert shipment with corresponding shipment/order ID is absent in shipments grid.
+ */
+class AssertShipmentNotInShipmentsGrid extends AbstractConstraint
+{
+    /**
+     * Assert shipment with corresponding shipment/order ID is absent in shipments grid.
+     *
+     * @param ShipmentIndex $shipmentIndex
+     * @param OrderInjectable $order
+     * @param array $ids
+     * @return void
+     */
+    public function processAssert(ShipmentIndex $shipmentIndex, OrderInjectable $order, array $ids)
+    {
+        $shipmentIndex->open();
+        $orderId = $order->getId();
+        $totalQty = $order->getTotalQtyOrdered();
+        foreach ($ids['shipmentIds'] as $key => $shipmentIds) {
+            $filter = [
+                'id' => $shipmentIds,
+                'order_id' => $orderId
+            ];
+            $filterQty = [
+                'total_qty_from' => $totalQty[$key],
+                'total_qty_to' => $totalQty[$key],
+            ];
+            $shipmentIndex->getShipmentsGrid()->search($filter + $filterQty);
+            \PHPUnit_Framework_Assert::assertFalse(
+                $shipmentIndex->getShipmentsGrid()->isRowVisible($filter, false),
+                'Shipment is present in shipment grid on shipment index page.'
+            );
+        }
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Shipment is absent in the shipment grid on shipment index page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreCodeInUrl.php b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreCodeInUrl.php
new file mode 100644
index 0000000000000000000000000000000000000000..c871866a337967c04a397f5abe665e9d3b329049
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreCodeInUrl.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Store\Test\Constraint;
+
+use Magento\Cms\Test\Page\CmsIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Mtf\Client\BrowserInterface;
+
+/**
+ * Assert that store code is present in the url.
+ */
+class AssertStoreCodeInUrl extends AbstractConstraint
+{
+    /**
+     * Assert store code in the home page url.
+     *
+     * @param CmsIndex $cmsIndex
+     * @param BrowserInterface $browser
+     * @param string $storeCode
+     * @return void
+     */
+    public function processAssert(CmsIndex $cmsIndex, BrowserInterface $browser, $storeCode)
+    {
+        $cmsIndex->open();
+        $cmsIndex->getLogoBlock()->clickOnLogo();
+        \PHPUnit_Framework_Assert::assertEquals(
+            $_ENV['app_frontend_url'] . $storeCode . '/',
+            $browser->getUrl(),
+            sprintf('Store code \'%s\' is not present in the url: %s', $storeCode, $browser->getUrl())
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Store code is present in the url.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreDisabledErrorSaveMessage.php b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreDisabledErrorSaveMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..ed74a913b247edf6f4ff19692bd552ce4592987e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreDisabledErrorSaveMessage.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Store\Test\Constraint;
+
+use Magento\Backend\Test\Page\Adminhtml\EditStore;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that after Store View save disabled error message appears.
+ */
+class AssertStoreDisabledErrorSaveMessage extends AbstractConstraint
+{
+    /**
+     * Disabled error message.
+     */
+    const ERROR_MESSAGE = 'The default store cannot be disabled';
+
+    /**
+     * Assert that after Store View save disabled error message appears.
+     *
+     * @param EditStore $editStore
+     * @return void
+     */
+    public function processAssert(EditStore $editStore)
+    {
+        \PHPUnit_Framework_Assert::assertEquals(
+            self::ERROR_MESSAGE,
+            $editStore->getMessagesBlock()->getErrorMessage(),
+            'Wrong error message is displayed.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Store View disabled error create message is present.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreGroupNoDeleteButton.php b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreGroupNoDeleteButton.php
new file mode 100644
index 0000000000000000000000000000000000000000..d77fa2e3134f82faddbd40e30743697554c3e52e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreGroupNoDeleteButton.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Store\Test\Constraint;
+
+use Magento\Backend\Test\Page\Adminhtml\NewGroupIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that 'Delete' button on StoreGroup view edit page is absent.
+ */
+class AssertStoreGroupNoDeleteButton extends AbstractConstraint
+{
+    /**
+     * Assert that 'Delete' button on StoreGroup view edit page is absent.
+     *
+     * @param NewGroupIndex $newGroupIndex
+     * @return void
+     */
+    public function processAssert(NewGroupIndex $newGroupIndex)
+    {
+        \PHPUnit_Framework_Assert::assertFalse(
+            $newGroupIndex->getFormPageActions()->checkDeleteButton(),
+            '\'Delete\' button on StoreGroup view edit page is present when it should not.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return '\'Delete\' button on StoreGroup view edit page is absent.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreNoDeleteButton.php b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreNoDeleteButton.php
new file mode 100644
index 0000000000000000000000000000000000000000..fb54b353328e14d93e27151a06e61519ef8f8bcc
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreNoDeleteButton.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Store\Test\Constraint;
+
+use Magento\Backend\Test\Page\Adminhtml\StoreNew;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that 'Delete' button on Store view edit page is absent.
+ */
+class AssertStoreNoDeleteButton extends AbstractConstraint
+{
+    /**
+     * Assert that 'Delete' button on Store view edit page is absent.
+     *
+     * @param StoreNew $storePage
+     * @return void
+     */
+    public function processAssert(StoreNew $storePage)
+    {
+        \PHPUnit_Framework_Assert::assertFalse(
+            $storePage->getFormPageActions()->checkDeleteButton(),
+            '\'Delete\' button on Store view edit page is present when it should not.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return '\'Delete\' button on Store view edit page is absent.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Store/GroupId.php b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Store/GroupId.php
index a5fa6d4a83cbe63cbcf6d6b15e5935787d5d2694..34b93054fd282b3c7ccab5767ae8fc215d388b17 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Store/GroupId.php
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Store/GroupId.php
@@ -31,6 +31,13 @@ class GroupId extends DataSource
     public function __construct(FixtureFactory $fixtureFactory, array $params, array $data = [])
     {
         $this->params = $params;
+
+        if (isset($data['storeGroup']) && $data['storeGroup'] instanceof StoreGroup) {
+            $this->storeGroup = $data['storeGroup'];
+            $this->data = $data['storeGroup']->getWebsiteId() . "/" . $data['storeGroup']->getName();
+            return;
+        }
+
         if (isset($data['dataset'])) {
             $storeGroup = $fixtureFactory->createByCode('storeGroup', ['dataset' => $data['dataset']]);
             /** @var StoreGroup $storeGroup */
@@ -44,11 +51,6 @@ class GroupId extends DataSource
             $this->data = $this->storeGroup->getWebsiteId() . "/" . $this->storeGroup->getName();
         }
 
-        if (isset($data['storeGroup']) && $data['storeGroup'] instanceof StoreGroup) {
-            $this->storeGroup = $data['storeGroup'];
-            $this->data = $data['storeGroup']->getWebsiteId() . "/" . $data['storeGroup']->getName();
-        }
-
         if (isset($data['value'])) {
             $this->data = $data['value'];
         }
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/StoreGroup/CategoryId.php b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/StoreGroup/CategoryId.php
index ccdc7b204894eb00a6afd255acbd3c56fc9fd0f6..32983d35c46e2ce318e64a3fcc7cd134bdfb8278 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/StoreGroup/CategoryId.php
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/StoreGroup/CategoryId.php
@@ -31,7 +31,10 @@ class CategoryId extends DataSource
     public function __construct(FixtureFactory $fixtureFactory, array $params, array $data = [])
     {
         $this->params = $params;
-        if (isset($data['dataset'])) {
+        if (isset($data['fixture']) || isset($data['category'])) {
+            $this->category = isset($data['fixture']) ? $data['fixture'] : $data['category'];
+            $this->data = $this->category->getName();
+        } elseif (isset($data['dataset'])) {
             $category = $fixtureFactory->createByCode('category', ['dataset' => $data['dataset']]);
             /** @var Category $category */
             if (!$category->getId()) {
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/StoreGroup/WebsiteId.php b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/StoreGroup/WebsiteId.php
index 985b4a91c35f8412eb614b1903a5e56ab8a410e1..1a25d3d6b6f83dd100d4e1699823e47b883432a5 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/StoreGroup/WebsiteId.php
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/StoreGroup/WebsiteId.php
@@ -31,7 +31,10 @@ class WebsiteId extends DataSource
     public function __construct(FixtureFactory $fixtureFactory, array $params, array $data = [])
     {
         $this->params = $params;
-        if (isset($data['dataset'])) {
+        if (isset($data['fixture'])) {
+            $this->website = $data['fixture'];
+            $this->data = $this->website->getName();
+        } elseif (isset($data['dataset'])) {
             $website = $fixtureFactory->createByCode('website', ['dataset' => $data['dataset']]);
             /** @var Website $website */
             if (!$website->getWebsiteId()) {
@@ -39,9 +42,6 @@ class WebsiteId extends DataSource
             }
             $this->website = $website;
             $this->data = $website->getName();
-        } elseif (isset($data['fixture'])) {
-            $this->website = $data['fixture'];
-            $this->data = $this->website->getName();
         }
     }
 
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/ConfigData.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fbaa409165f14632e81f27009612d3a5a8c82470
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/ConfigData.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * 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/Magento/Mtf/Repository/etc/repository.xsd">
+    <repository class="Magento\Config\Test\Repository\ConfigData">
+        <dataset name="add_store_code_to_urls">
+            <field name="web/url/use_store" xsi:type="array">
+                <item name="scope" xsi:type="string">admin</item>
+                <item name="scope_id" xsi:type="number">1</item>
+                <item name="label" xsi:type="string">Yes</item>
+                <item name="value" xsi:type="number">1</item>
+            </field>
+        </dataset>
+
+        <dataset name="add_store_code_to_urls_rollback">
+            <field name="web/url/use_store" xsi:type="array">
+                <item name="scope" xsi:type="string">admin</item>
+                <item name="scope_id" xsi:type="number">1</item>
+                <item name="label" xsi:type="string">No</item>
+                <item name="value" xsi:type="number">0</item>
+            </field>
+        </dataset>
+    </repository>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Store.xml b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Store.xml
index 37faba3d75524304919c65cf391ee4211ef9fdae..5a7691042fde8dda5b2bd998dc6cef2a75bbe059 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Store.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Store.xml
@@ -44,6 +44,7 @@
             <field name="code" xsi:type="string">de%isolation%</field>
             <field name="is_active" xsi:type="string">Enabled</field>
         </dataset>
+
         <dataset name="custom_store">
             <field name="group_id" xsi:type="array">
                 <item name="dataset" xsi:type="string">custom_new_group</item>
@@ -61,5 +62,23 @@
             <field name="code" xsi:type="string">code_%isolation%</field>
             <field name="is_active" xsi:type="string">Enabled</field>
         </dataset>
+
+        <dataset name="store_new_1">
+            <field name="group_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">store_group_new_1</item>
+            </field>
+            <field name="name" xsi:type="string">New_Store_%isolation%</field>
+            <field name="code" xsi:type="string">store_group_new_1_%isolation%</field>
+            <field name="is_active" xsi:type="string">Enabled</field>
+        </dataset>
+
+        <dataset name="store_new_2">
+            <field name="group_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">store_group_new_2</item>
+            </field>
+            <field name="name" xsi:type="string">New_Store_2_%isolation%</field>
+            <field name="code" xsi:type="string">store_group_new_2_%isolation%</field>
+            <field name="is_active" xsi:type="string">Enabled</field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/StoreGroup.xml b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/StoreGroup.xml
index f07c79a8967d56b5b241feb049cd402f6d90ddef..b3fa6a52b2f59ee1c4421395b1cc900fd3ac4708 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/StoreGroup.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/StoreGroup.xml
@@ -37,5 +37,25 @@
                 <item name="dataset" xsi:type="string">default_category</item>
             </field>
         </dataset>
+
+        <dataset name="store_group_new_1">
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">website_new_1</item>
+            </field>
+            <field name="name" xsi:type="string">New_Store_Group_%isolation%</field>
+            <field name="root_category_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default_category</item>
+            </field>
+        </dataset>
+
+        <dataset name="store_group_new_2">
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">website_new_2</item>
+            </field>
+            <field name="name" xsi:type="string">New_Store_Group_2_%isolation%</field>
+            <field name="root_category_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">root_category</item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Website.xml b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Website.xml
index 5c2ec69efca98b581708ffd2eb4441d8275ee073..0a7552e44b9950127e185bfd810c3264bc36b511 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Website.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Website.xml
@@ -29,5 +29,15 @@
             <field name="name" xsi:type="string">Web_Site_%isolation%</field>
             <field name="code" xsi:type="string">code_%isolation%</field>
         </dataset>
+
+        <dataset name="website_new_1">
+            <field name="name" xsi:type="string">New_Website_%isolation%</field>
+            <field name="code" xsi:type="string">new_%isolation%</field>
+        </dataset>
+
+        <dataset name="website_new_2">
+            <field name="name" xsi:type="string">New_Website_2_%isolation%</field>
+            <field name="code" xsi:type="string">new2_%isolation%</field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/AccessAdminWithStoreCodeInUrlTest.php b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/AccessAdminWithStoreCodeInUrlTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..079cf1384ef812c1bb8b5a1f7ce39ed6158774d4
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/AccessAdminWithStoreCodeInUrlTest.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Store\Test\TestCase;
+
+use Magento\Mtf\TestCase\Injectable;
+use Magento\Mtf\TestStep\TestStepFactory;
+
+/**
+ * Steps:
+ * 1. Enable 'Add Store Code to Urls'.
+ * 2. Log out from Admin.
+ * 3. Perform all assertions.
+ *
+ * @ZephyrId MAGETWO-42720
+ */
+class AccessAdminWithStoreCodeInUrlTest extends Injectable
+{
+    /* tags */
+    const MVP = 'no';
+    /* end tags */
+
+    /**
+     * Configuration setting.
+     *
+     * @var string
+     */
+    private $configData;
+
+    /**
+     * Step factory.
+     *
+     * @var TestStepFactory
+     */
+    private $stepFactory;
+
+    /**
+     * Inject step factory.
+     *
+     * @param TestStepFactory $stepFactory
+     * @return void
+     */
+    public function __inject(TestStepFactory $stepFactory)
+    {
+        $this->stepFactory = $stepFactory;
+    }
+
+    /**
+     * Set config and log out from Admin.
+     *
+     * @param string $configData
+     * @return void
+     */
+    public function test($configData)
+    {
+        $this->configData = $configData;
+        $this->stepFactory->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData]
+        )->run();
+        $this->stepFactory->create(
+            \Magento\User\Test\TestStep\LogoutUserOnBackendStep::class,
+            ['configData' => $this->configData]
+        )->run();
+    }
+
+    /**
+     * Reset config settings to default.
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        $this->stepFactory->create(
+            \Magento\Config\Test\TestStep\SetupConfigurationStep::class,
+            ['configData' => $this->configData, 'rollback' => true]
+        )->run();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/AccessAdminWithStoreCodeInUrlTest.xml b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/AccessAdminWithStoreCodeInUrlTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..432d0e24d2fa2726af2c6990715f7a7207a9b109
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/AccessAdminWithStoreCodeInUrlTest.xml
@@ -0,0 +1,18 @@
+<?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\Store\Test\TestCase\AccessAdminWithStoreCodeInUrlTest" summary="Access admin when store code added to URL" ticketId="MAGETWO-42720">
+        <variation name="AccessAdminWithStoreCodeInUrlTestVariation1" summary="Access admin when store code added to URL" ticketId="MAGETWO-42720">
+            <data name="configData" xsi:type="string">add_store_code_to_urls</data>
+            <data name="user/dataset" xsi:type="string">default</data>
+            <data name="storeCode" xsi:type="string">default</data>
+            <constraint name="Magento\User\Test\Constraint\AssertUserSuccessLogin" />
+            <constraint name="Magento\Store\Test\Constraint\AssertStoreCodeInUrl" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateStoreEntityTest.xml b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateStoreEntityTest.xml
index 26d9aa9beba0acc098558d8fd1f6aacb9083cb5d..fb43cc3f08c06f3bf1ab9a8a94c7739ffc9f301f 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateStoreEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateStoreEntityTest.xml
@@ -50,5 +50,18 @@
             <constraint name="Magento\Store\Test\Constraint\AssertStoreSuccessSaveMessage" />
             <constraint name="Magento\Store\Test\Constraint\AssertStoreInGrid" />
         </variation>
+        <variation name="CreateStoreEntityTestVariation5" summary="Check the absence of delete button" ticketId="MAGETWO-17475">
+            <data name="store/dataset" xsi:type="string">custom_store</data>
+            <constraint name="Magento\Store\Test\Constraint\AssertStoreSuccessSaveMessage" />
+            <constraint name="Magento\Store\Test\Constraint\AssertStoreForm" />
+            <constraint name="Magento\Store\Test\Constraint\AssertStoreNoDeleteButton" />
+        </variation>
+        <variation name="CreateDisabledStoreView" summary="Create disabled store view" ticketId="MAGETWO-17475">
+            <data name="store/data/group_id/dataset" xsi:type="string">custom_new_group</data>
+            <data name="store/data/name" xsi:type="string">store_name_%isolation%</data>
+            <data name="store/data/code" xsi:type="string">storecode_%isolation%</data>
+            <data name="store/data/is_active" xsi:type="string">Disabled</data>
+            <constraint name="Magento\Store\Test\Constraint\AssertStoreDisabledErrorSaveMessage" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateStoreGroupEntityTest.xml b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateStoreGroupEntityTest.xml
index 39adbb9c418403469cfd5f82697619c5d89218be..b083214841cca0253f7448572d9214ca2adeb305 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateStoreGroupEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/CreateStoreGroupEntityTest.xml
@@ -26,5 +26,11 @@
             <constraint name="Magento\Store\Test\Constraint\AssertStoreGroupForm" />
             <constraint name="Magento\Store\Test\Constraint\AssertStoreGroupOnStoreViewForm" />
         </variation>
+        <variation name="CreateStoreGroupEntityTestVariation3" summary="Check the absence of delete button" ticketId="MAGETWO-17475">
+            <data name="storeGroup/dataset" xsi:type="string">custom_new_group</data>
+            <constraint name="Magento\Store\Test\Constraint\AssertStoreGroupSuccessSaveMessage" />
+            <constraint name="Magento\Store\Test\Constraint\AssertStoreGroupForm" />
+            <constraint name="Magento\Store\Test\Constraint\AssertStoreGroupNoDeleteButton" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Swatches/Test/Constraint/AssertSwatchConfigurableProductPage.php b/dev/tests/functional/tests/app/Magento/Swatches/Test/Constraint/AssertSwatchConfigurableProductPage.php
index 460a13ce49d704f30f513af5c8f3189c45f3ffc4..8f910174273420944afb5587d85f1a9ffa16afd4 100644
--- a/dev/tests/functional/tests/app/Magento/Swatches/Test/Constraint/AssertSwatchConfigurableProductPage.php
+++ b/dev/tests/functional/tests/app/Magento/Swatches/Test/Constraint/AssertSwatchConfigurableProductPage.php
@@ -26,12 +26,7 @@ class AssertSwatchConfigurableProductPage extends AssertProductPage
     ) {
         $this->product = $product;
         $this->productView = $catalogProductView->getProductViewWithSwatchesBlock();
-        $this->objectManager->create(
-            \Magento\Swatches\Test\TestStep\AddProductToCartFromCatalogCategoryPageStep::class,
-            [
-                'product' => $product
-            ]
-        )->run();
+
         // we need this line for waiti until page will be fully loaded
         $this->productView->getSelectedSwatchOptions($this->product);
         $errors = $this->verify();
diff --git a/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/AddConfigurableProductWithSwatchToShopingCartTest.php b/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/AddConfigurableProductWithSwatchToShopingCartTest.php
deleted file mode 100644
index 60cc61f7f0f79319336d57d0d81289de6fe31cab..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/AddConfigurableProductWithSwatchToShopingCartTest.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-/**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-namespace Magento\Swatches\Test\TestCase;
-
-use Magento\Mtf\TestCase\Scenario;
-
-/**
- * Preconditions:
- * 1. Configure text swatch attribute.
- * 2. Create configurable product with this attribute
- * 3. Open it on catalog page
- * 4. Click on 'Add to Cart' button
- *
- * Steps:
- * 1. Go to Frontend.
- * 2. Open category page with created product
- * 3. Click on 'Add to Cart' button
- * 4. Perform asserts
- *
- * @group Configurable_Product
- * @ZephyrId MAGETWO-59958
- */
-class AddConfigurableProductWithSwatchToShopingCartTest extends Scenario
-{
-    /**
-     * Runs add configurable product with swatches attributes test.
-     *
-     * @return void
-     */
-    public function test()
-    {
-        $this->executeScenario();
-    }
-}
diff --git a/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/AddConfigurableProductWithSwatchToShopingCartTest.xml b/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/AddConfigurableProductWithSwatchToShopingCartTest.xml
deleted file mode 100644
index adf8d71395ccb9c4b714ad58887ec741391871a2..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/AddConfigurableProductWithSwatchToShopingCartTest.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?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\Swatches\Test\TestCase\AddConfigurableProductWithSwatchToShopingCartTest" summary="Create text swatch attribute" ticketId="MAGETWO-47017">
-        <variation name="AddConfigurableProductWithSwatchToShopingCartTest1">
-            <data name="attributeTypeAction" xsi:type="string">addOptions</data>
-            <data name="product" xsi:type="string">configurableProductSwatch::product_with_text_swatch</data>
-            <constraint name="Magento\Checkout\Test\Constraint\AssertCartItemsOptions" />
-        </variation>
-    </testCase>
-</config>
diff --git a/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/AddConfigurableProductWithSwatchToShoppingCartTest.php b/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/AddConfigurableProductWithSwatchToShoppingCartTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6f05c1a7cfa597042c68aa1fbfa1c010242473f3
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/AddConfigurableProductWithSwatchToShoppingCartTest.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Swatches\Test\TestCase;
+
+use Magento\Mtf\TestCase\Injectable;
+use Magento\ConfigurableProduct\Test\Fixture\ConfigurableProduct;
+use Magento\Mtf\TestStep\TestStepFactory;
+use Magento\Catalog\Test\Page\Category\CatalogCategoryView;
+
+/**
+ * Preconditions:
+ * 1. Configure text swatch attribute.
+ * 2. Create configurable product with this attribute
+ * 3. Open it on catalog page
+ * 4. Click on 'Add to Cart' button
+ *
+ * Steps:
+ * 1. Go to Frontend.
+ * 2. Open category page with created product
+ * 3. Click on 'Add to Cart' button
+ * 4. Perform asserts
+ *
+ * @group Configurable_Product
+ * @ZephyrId MAGETWO-59958, MAGETWO-59979
+ */
+class AddConfigurableProductWithSwatchToShoppingCartTest extends Injectable
+{
+    /**
+     * Factory for Test Steps.
+     *
+     * @var TestStepFactory
+     */
+    private $testStepFactory;
+
+    /**
+     * Page of catalog category view.
+     *
+     * @var CatalogCategoryView
+     */
+    private $categoryView;
+
+    /**
+     * Injection data.
+     *
+     * @param TestStepFactory $testStepFactory
+     * @param CatalogCategoryView $categoryView
+     * @return void
+     */
+    public function __inject(
+        TestStepFactory $testStepFactory,
+        CatalogCategoryView $categoryView
+    ) {
+        $this->testStepFactory = $testStepFactory;
+        $this->categoryView = $categoryView;
+    }
+
+    /**
+     * Runs add configurable product with swatches attributes test.
+     *
+     * @param ConfigurableProduct $product
+     * @param bool $addToCart
+     * @return array
+     */
+    public function test(ConfigurableProduct $product, $addToCart)
+    {
+        $product->persist();
+        $cart = $this->testStepFactory->create(
+            \Magento\Swatches\Test\TestStep\AddProductToCartFromCatalogCategoryPageStep::class,
+            [
+                'product' => $product
+            ]
+        )->run()['cart'];
+        if ($addToCart) {
+            $this->categoryView->getMessagesBlock()->waitSuccessMessage();
+        }
+
+        return ['cart' => $cart];
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/AddConfigurableProductWithSwatchToShoppingCartTest.xml b/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/AddConfigurableProductWithSwatchToShoppingCartTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a786094693960aba7fe1ae4a40b9b144b05f050d
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/AddConfigurableProductWithSwatchToShoppingCartTest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\Swatches\Test\TestCase\AddConfigurableProductWithSwatchToShoppingCartTest" summary="Create text swatch attribute" ticketId="MAGETWO-47017">
+        <variation name="AddConfigurableProductWithSwatchToShoppingCartTest1" summary="Add configurable product to cart with swatch options only" ticketId="MAGETWO-59958">
+            <data name="attributeTypeAction" xsi:type="string">addOptions</data>
+            <data name="product/dataset" xsi:type="string">product_with_text_swatch</data>
+            <data name="addToCart" xsi:type="boolean">true</data>
+            <constraint name="Magento\Checkout\Test\Constraint\AssertCartItemsOptions" />
+        </variation>
+        <variation name="AddConfigurableProductWithSwatchToShoppingCartTest2" summary="Add configurable product to cart with mixed option types" ticketId="MAGETWO-59979">
+            <data name="attributeTypeAction" xsi:type="string">addOptions</data>
+            <data name="product/dataset" xsi:type="string">product_with_text_swatch_and_size</data>
+            <data name="addToCart" xsi:type="boolean">false</data>
+            <constraint name="Magento\Swatches\Test\Constraint\AssertSwatchConfigurableProductPage" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/TryToAddConfigurableProductWithSwatchToShopingCartTest.php b/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/TryToAddConfigurableProductWithSwatchToShopingCartTest.php
deleted file mode 100644
index ac3016ade3f016b82a856677715db6c93736c1ef..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/TryToAddConfigurableProductWithSwatchToShopingCartTest.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-/**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-namespace Magento\Swatches\Test\TestCase;
-
-use Magento\Mtf\TestCase\Scenario;
-
-/**
- * Preconditions:
- * 1. Configure text swatch attribute.
- * 2. Create configurable product with this attribute
- * 3. Open it on catalog page
- * 4. Click on 'Add to Cart' button
- *
- * Steps:
- * 1. Go to Frontend.
- * 2. Open category page with created product
- * 3. Click on 'Add to Cart' button
- * 4. Perform asserts
- *
- * @group Configurable_Product
- * @ZephyrId TODO: MAGETWO-59979
- */
-class TryToAddConfigurableProductWithSwatchToShopingCartTest extends Scenario
-{
-    /**
-     * Runs add configurable product with swatches attributes test.
-     *
-     * @return void
-     */
-    public function test()
-    {
-        $this->executeScenario();
-    }
-}
diff --git a/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/TryToAddConfigurableProductWithSwatchToShopingCartTest.xml b/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/TryToAddConfigurableProductWithSwatchToShopingCartTest.xml
deleted file mode 100644
index 4cb7a3e01676f09c6c3e6b9ffcd3d85fb9abbe4a..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/Swatches/Test/TestCase/TryToAddConfigurableProductWithSwatchToShopingCartTest.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?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\Swatches\Test\TestCase\TryToAddConfigurableProductWithSwatchToShopingCartTest" summary="Create text swatch attribute" ticketId="MAGETWO-47017">
-        <variation name="TryToAddConfigurableProductWithSwatchToShopingCartTest1">
-            <data name="attributeTypeAction" xsi:type="string">addOptions</data>
-            <data name="product" xsi:type="string">configurableProductSwatch::product_with_text_swatch_and_size</data>
-            <constraint name="Magento\Swatches\Test\Constraint\AssertSwatchConfigurableProductPage" />
-        </variation>
-    </testCase>
-</config>
diff --git a/dev/tests/functional/tests/app/Magento/Swatches/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Swatches/Test/etc/testcase.xml
deleted file mode 100644
index f2e30c42a7a859e52ad129eda213aa8b1e597aad..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/Swatches/Test/etc/testcase.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0"?>
-<!--
-/**
- * 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/Magento/Mtf/TestCase/etc/testcase.xsd">
-    <scenario name="AddConfigurableProductWithSwatchToShopingCartTest" firstStep="createProduct">
-        <step name="createProduct" module="Magento_Catalog" next="addProductToCartFromCatalogCategoryPage" />
-        <step name="addProductToCartFromCatalogCategoryPage" module="Magento_Swatches" />
-    </scenario>
-    <scenario name="TryToAddConfigurableProductWithSwatchToShopingCartTest" firstStep="createProduct">
-        <step name="createProduct" module="Magento_Catalog" />
-    </scenario>
-</config>
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/ConfigData.xml
index 33ecac40bfe3aaba2f5953b3e2c2cdbdbc4a03e4..5a51be9a9879a66c05b4b1e4e40309f24c80de92 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/ConfigData.xml
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/ConfigData.xml
@@ -164,7 +164,7 @@
             <field name="tax/calculation/apply_after_discount" xsi:type="array">
                 <item name="scope" xsi:type="string">tax</item>
                 <item name="scope_id" xsi:type="number">1</item>
-                <item name="label" xsi:type="string">Before Discount</item>
+                <item name="label" xsi:type="string">After Discount</item>
                 <item name="value" xsi:type="number">0</item>
             </field>
             <field name="tax/calculation/discount_tax" xsi:type="array">
@@ -541,6 +541,15 @@
             </field>
         </dataset>
 
+        <dataset name="row_cat_incl_ship_excl_before_disc_on_incl_rollback">
+            <field name="tax/calculation/apply_after_discount" xsi:type="array">
+                <item name="scope" xsi:type="string">tax</item>
+                <item name="scope_id" xsi:type="number">1</item>
+                <item name="label" xsi:type="string">After Discount</item>
+                <item name="value" xsi:type="number">1</item>
+            </field>
+        </dataset>
+
         <dataset name="unit_cat_incl_ship_incl_before_disc_on_incl">
             <field name="tax/calculation/algorithm" xsi:type="array">
                 <item name="scope" xsi:type="string">tax</item>
@@ -580,6 +589,15 @@
             </field>
         </dataset>
 
+        <dataset name="unit_cat_incl_ship_incl_before_disc_on_incl_rollback">
+            <field name="tax/calculation/apply_after_discount" xsi:type="array">
+                <item name="scope" xsi:type="string">tax</item>
+                <item name="scope_id" xsi:type="number">1</item>
+                <item name="label" xsi:type="string">After Discount</item>
+                <item name="value" xsi:type="number">1</item>
+            </field>
+        </dataset>
+
         <dataset name="total_cat_excl_ship_incl_before_disc_on_incl">
             <field name="tax/calculation/algorithm" xsi:type="array">
                 <item name="scope" xsi:type="string">tax</item>
@@ -619,6 +637,15 @@
             </field>
         </dataset>
 
+        <dataset name="total_cat_excl_ship_incl_before_disc_on_incl_rollback">
+            <field name="tax/calculation/apply_after_discount" xsi:type="array">
+                <item name="scope" xsi:type="string">tax</item>
+                <item name="scope_id" xsi:type="number">1</item>
+                <item name="label" xsi:type="string">After Discount</item>
+                <item name="value" xsi:type="number">1</item>
+            </field>
+        </dataset>
+
         <dataset name="unit_cat_excl_ship_excl_after_disc_on_excl">
             <field name="tax/calculation/algorithm" xsi:type="array">
                 <item name="scope" xsi:type="string">tax</item>
@@ -697,6 +724,15 @@
             </field>
         </dataset>
 
+        <dataset name="total_cat_incl_ship_excl_before_disc_on_excl_rollback">
+            <field name="tax/calculation/apply_after_discount" xsi:type="array">
+                <item name="scope" xsi:type="string">tax</item>
+                <item name="scope_id" xsi:type="number">1</item>
+                <item name="label" xsi:type="string">After Discount</item>
+                <item name="value" xsi:type="number">1</item>
+            </field>
+        </dataset>
+
         <dataset name="total_cat_excl_ship_incl_after_disc_on_incl">
             <field name="tax/calculation/algorithm" xsi:type="array">
                 <item name="scope" xsi:type="string">tax</item>
diff --git a/dev/tests/functional/tests/app/Magento/Theme/Test/Block/Html/Logo.php b/dev/tests/functional/tests/app/Magento/Theme/Test/Block/Html/Logo.php
new file mode 100644
index 0000000000000000000000000000000000000000..d05882dc9405387a082d3dff6ee81cfe26c38118
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Theme/Test/Block/Html/Logo.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Theme\Test\Block\Html;
+
+use Magento\Mtf\Block\Block;
+
+/**
+ * Logo block.
+ */
+class Logo extends Block
+{
+    /**
+     * Click on logo element.
+     *
+     * @return void
+     */
+    public function clickOnLogo()
+    {
+        $this->_rootElement->click();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php
index c5968c8e936f8a5bead20016d9c70d699b8c1a0c..be7a650d77e1c3ebe56409b5e38f9db8ef8e97ab 100644
--- a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php
+++ b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php
@@ -95,16 +95,27 @@ class DataGrid extends Grid
     protected $columnHeader = './/*[@data-role="grid-wrapper"]//th/span[.="%s"]';
 
     /**
+     * Grid row xpath locator.
+     *
      * @var string
      */
-    protected $rowById = "//tr[//input[@data-action='select-row' and @value='%s']]";
+    protected $rowById = ".//tr[td//input[@data-action='select-row' and @value='%s']]";
 
-    // @codingStandardsIgnoreStart
     /**
+     * Column header number.
+     *
      * @var string
      */
-    private $cellByHeader = "//td[count(//th[span[.='%s']][not(ancestor::*[@class='sticky-header'])]/preceding-sibling::th)+1]";
+    protected $columnNumber = ".//th[span[.='%s']][not(ancestor::*[@class='sticky-header'])]/preceding-sibling::th";
 
+    /**
+     * Cell number.
+     *
+     * @var string
+     */
+    protected $cellByHeader = "//td[%s+1]";
+
+    // @codingStandardsIgnoreStart
     /**
      * Admin data grid header selector.
      *
@@ -389,6 +400,8 @@ class DataGrid extends Grid
     }
 
     /**
+     * Sort grid by column.
+     *
      * @param string $columnLabel
      */
     public function sortByColumn($columnLabel)
@@ -396,6 +409,7 @@ class DataGrid extends Grid
         $this->waitLoader();
         $this->getTemplateBlock()->waitForElementNotVisible($this->loader);
         $this->_rootElement->find(sprintf($this->columnHeader, $columnLabel), Locator::SELECTOR_XPATH)->click();
+        $this->waitLoader();
     }
 
     /**
@@ -434,7 +448,11 @@ class DataGrid extends Grid
     {
         $this->waitLoader();
         $this->getTemplateBlock()->waitForElementNotVisible($this->loader);
-        $selector = sprintf($this->rowById, $id) . sprintf($this->cellByHeader, $headerLabel);
+        $columnNumber = count(
+            $this->_rootElement->getElements(sprintf($this->columnNumber, $headerLabel), Locator::SELECTOR_XPATH)
+        );
+        $selector = sprintf($this->rowById, $id) . sprintf($this->cellByHeader, $columnNumber);
+
         return $this->_rootElement->find($selector, Locator::SELECTOR_XPATH)->getText();
     }
 
diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Messages.php b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Messages.php
new file mode 100644
index 0000000000000000000000000000000000000000..c29e56d421bc340690989bae377148453e662619
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Messages.php
@@ -0,0 +1,161 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Ui\Test\Block;
+
+use Magento\Mtf\Block\Block;
+use Magento\Mtf\Client\Locator;
+
+/**
+ * Global messages block.
+ */
+class Messages extends Block
+{
+    /**
+     * Success message selector.
+     *
+     * @var string
+     */
+    protected $successMessage = '[data-ui-id$=message-success]';
+
+    /**
+     * Last success message selector.
+     *
+     * @var string
+     */
+    protected $lastSuccessMessage = '[data-ui-id$=message-success]:last-child';
+
+    /**
+     * Error message selector.
+     *
+     * @var string
+     */
+    protected $errorMessage = '[data-ui-id$=message-error]';
+
+    /**
+     * Notice message selector.
+     *
+     * @var string
+     */
+    protected $noticeMessage = '[data-ui-id$=message-notice]';
+
+    /**
+     * Warning message selector.
+     *
+     * @var string
+     */
+    protected $warningMessage = '[data-ui-id$=message-warning]';
+
+    /**
+     * Wait for success message.
+     *
+     * @return bool
+     */
+    public function waitSuccessMessage()
+    {
+        return $this->waitForElementVisible($this->successMessage, Locator::SELECTOR_CSS);
+    }
+
+    /**
+     * Get all success messages which are present on the page.
+     *
+     * @return array
+     */
+    public function getSuccessMessages()
+    {
+        $this->waitForElementVisible($this->successMessage);
+        $elements = $this->_rootElement->getElements($this->successMessage);
+
+        $messages = [];
+        foreach ($elements as $element) {
+            $messages[] = $element->getText();
+        }
+
+        return $messages;
+    }
+
+    /**
+     * Get all notice messages which are present on the page.
+     *
+     * @return array
+     */
+    public function getNoticeMessages()
+    {
+        $this->waitForElementVisible($this->noticeMessage);
+        $elements = $this->_rootElement->getElements($this->noticeMessage);
+
+        $messages = [];
+        foreach ($elements as $element) {
+            $messages[] = $element->getText();
+        }
+
+        return $messages;
+    }
+
+    /**
+     * Get last success message which is present on the page.
+     *
+     * @return string
+     */
+    public function getSuccessMessage()
+    {
+        $this->waitForElementVisible($this->successMessage);
+
+        return $this->_rootElement->find($this->lastSuccessMessage)->getText();
+    }
+
+    /**
+     * Wait for element is visible in the page.
+     *
+     * @param string $selector
+     * @param string $strategy
+     * @return bool|null
+     */
+    public function waitForElementVisible($selector, $strategy = Locator::SELECTOR_CSS)
+    {
+        $browser = $this->browser;
+        return $browser->waitUntil(
+            function () use ($browser, $selector, $strategy) {
+                $message = $browser->find($selector, $strategy);
+                return $message->isVisible() ? true : null;
+            }
+        );
+    }
+
+    /**
+     * Get all error message which is present on the page.
+     *
+     * @return string
+     */
+    public function getErrorMessage()
+    {
+        return $this->_rootElement
+            ->find($this->errorMessage, Locator::SELECTOR_CSS)
+            ->getText();
+    }
+
+    /**
+     * Get notice message which is present on the page.
+     *
+     * @return string
+     */
+    public function getNoticeMessage()
+    {
+        $this->waitForElementVisible($this->noticeMessage);
+        return $this->_rootElement->find($this->noticeMessage)->getText();
+    }
+
+    /**
+     * Get warning message which is present on the page.
+     *
+     * @return string
+     */
+    public function getWarningMessage()
+    {
+        $this->waitForElementVisible($this->warningMessage);
+        return $this->_rootElement->find($this->warningMessage)->getText();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Category/Grid.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Category/Grid.php
index 54de30e734d902d8bddf9be41059e23fe42b21ad..19ca7c2b520dc4f97b21a5a36dd6b9ea945d1e1a 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Category/Grid.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Category/Grid.php
@@ -26,5 +26,13 @@ class Grid extends ParentGrid
         'target_path' => [
             'selector' => 'input[name="target_path"]',
         ],
+        'store_id' => [
+            'selector' => 'select[name="store_id"]',
+            'input' => 'select',
+        ],
+        'redirect_type' => [
+            'selector' => 'select[name="redirect_type"]',
+            'input' => 'select',
+        ],
     ];
 }
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteAfterDeletingCategory.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteAfterDeletingCategory.php
new file mode 100644
index 0000000000000000000000000000000000000000..c2611b67febb8d582072c0d5edf67c145832c84c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteAfterDeletingCategory.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\UrlRewrite\Test\Constraint;
+
+use Magento\Catalog\Test\Fixture\CatalogProductSimple;
+use Magento\UrlRewrite\Test\Fixture\UrlRewrite;
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogCategoryEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogCategoryIndex;
+use Magento\UrlRewrite\Test\Page\Adminhtml\UrlRewriteIndex;
+
+/**
+ * Assert that url rewrites for product and category are deleted after deleting category.
+ */
+class AssertUrlRewriteAfterDeletingCategory extends AbstractConstraint
+{
+    /**
+     * Assert that url rewrites are not present in grid.
+     *
+     * @param UrlRewrite $urlRewrite
+     * @param CatalogProductSimple $product
+     * @param CatalogCategoryIndex $catalogCategoryIndex
+     * @param CatalogCategoryEdit $catalogCategoryEdit
+     * @param UrlRewriteIndex $urlRewriteIndex
+     * @param AssertUrlRewriteNotInGrid $assertUrlRewrite
+     * @param AssertUrlRewriteCategoryNotInGrid $assertCategoryUrlRewrite
+     * @return void
+     */
+    public function processAssert(
+        UrlRewrite $urlRewrite,
+        CatalogProductSimple $product,
+        CatalogCategoryIndex $catalogCategoryIndex,
+        CatalogCategoryEdit $catalogCategoryEdit,
+        UrlRewriteIndex $urlRewriteIndex,
+        AssertUrlRewriteNotInGrid $assertUrlRewrite,
+        AssertUrlRewriteCategoryNotInGrid $assertCategoryUrlRewrite
+    ) {
+        $category = $product->getDataFieldConfig('category_ids')['source']->getCategories()[0];
+        $catalogCategoryIndex->open();
+        $catalogCategoryIndex->getTreeCategories()->selectCategory($category);
+        $catalogCategoryEdit->getFormPageActions()->delete();
+        $catalogCategoryEdit->getModalBlock()->acceptAlert();
+
+        $assertCategoryUrlRewrite->processAssert($urlRewriteIndex, $category);
+        $assertUrlRewrite->processAssert($urlRewriteIndex, $urlRewrite);
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'URL rewrites are deleted.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteCategoryInGrid.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteCategoryInGrid.php
index 3630bd697b8593a966f4ed93b67794b80b6da185..1e01ea5c6e32225ede8164cf355387a42b793f6a 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteCategoryInGrid.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteCategoryInGrid.php
@@ -9,34 +9,171 @@ namespace Magento\UrlRewrite\Test\Constraint;
 use Magento\Catalog\Test\Fixture\Category;
 use Magento\Mtf\Constraint\AbstractConstraint;
 use Magento\UrlRewrite\Test\Page\Adminhtml\UrlRewriteIndex;
+use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator;
 
 /**
- * Class AssertUrlRewriteCategoryInGrid
- * Assert that url category in grid
+ * Assert that url rewrite category in grid.
  */
 class AssertUrlRewriteCategoryInGrid extends AbstractConstraint
 {
+    /**
+     * Value for no redirect type in grid.
+     */
+    const REDIRECT_TYPE_NO = 'No';
+
+    /**
+     * Curl transport on webapi.
+     *
+     * @var WebapiDecorator
+     */
+    private $webApi;
+
+    /**
+     * Url rewrite index page.
+     *
+     * @var UrlRewriteIndex
+     */
+    private $urlRewriteIndex;
+
     /**
      * Assert that url rewrite category in grid.
      *
      * @param Category $category
+     * @param WebapiDecorator $webApi
      * @param UrlRewriteIndex $urlRewriteIndex
+     * @param Category $parentCategory
+     * @param Category $childCategory
+     * @param string|null $nestingLevel
      * @param string $filterByPath
+     * @param string $redirectType
      * @return void
      */
     public function processAssert(
         Category $category,
+        WebapiDecorator $webApi,
         UrlRewriteIndex $urlRewriteIndex,
-        $filterByPath = 'target_path'
+        Category $parentCategory = null,
+        Category $childCategory = null,
+        $nestingLevel = null,
+        $filterByPath = 'target_path',
+        $redirectType = 'Permanent (301)'
     ) {
+        $this->urlRewriteIndex = $urlRewriteIndex;
+        $this->webApi = $webApi;
+
         $urlRewriteIndex->open();
-        $filter = [$filterByPath => strtolower($category->getUrlKey())];
+        $categoryId = $this->getCategoryId($category, $childCategory);
+        $nestingPath = $this->getNestingPath($category, $nestingLevel);
+
+        $filter = [
+            'request_path' => $nestingPath,
+            'target_path' => 'catalog/category/view/id/' . $categoryId,
+            'redirect_type' => self::REDIRECT_TYPE_NO
+        ];
+        if ($parentCategory && $childCategory) {
+            $filter['request_path'] =
+                strtolower($parentCategory->getUrlKey() . '/' . $childCategory->getUrlKey() . '.html');
+        }
+        $this->rowVisibleAssertion($filter);
+
+        if ($redirectType != self::REDIRECT_TYPE_NO) {
+            if ($parentCategory && $childCategory) {
+                $urlPath = strtolower($parentCategory->getUrlKey() . '/' . $childCategory->getUrlKey() . '.html');
+                $filter = [
+                    'request_path' => $nestingPath,
+                    'target_path' => $urlPath,
+                    'redirect_type' => $redirectType
+                ];
+            } else {
+                $filter = [$filterByPath => strtolower($category->getUrlKey())];
+            }
+            $this->rowVisibleAssertion($filter);
+        }
+    }
+
+    /**
+     * Get category id.
+     *
+     * @param Category $category
+     * @param Category|null $childCategory
+     * @return int
+     */
+    private function getCategoryId(Category $category, Category $childCategory = null)
+    {
+        return ($childCategory ? $childCategory->getId() : $category->getId())
+            ? $category->getId()
+            : $this->retrieveCategory($category)['id'];
+    }
+
+    /**
+     * Assert that url rewrite category in grid.
+     *
+     * @param array $filter
+     * @return void
+     */
+    private function rowVisibleAssertion(array $filter)
+    {
+        $filterRow = implode(', ', $filter);
         \PHPUnit_Framework_Assert::assertTrue(
-            $urlRewriteIndex->getUrlRedirectGrid()->isRowVisible($filter, true, false),
-            'URL Rewrite with request path "' . $category->getUrlKey() . '" is absent in grid.'
+            $this->urlRewriteIndex->getUrlRedirectGrid()->isRowVisible($filter, true, false),
+            'URL Rewrite with request path "' . $filterRow . '" is absent in grid.'
         );
     }
 
+    /**
+     * Return nesting url path.
+     *
+     * @param Category $category
+     * @param int $nestingLevel
+     * @return string
+     */
+    private function getNestingPath(Category $category, $nestingLevel)
+    {
+        if ($nestingLevel === null) {
+            return strtolower($category->getUrlKey() . '.html');
+        }
+        $filterByRequestPathCondition = [];
+        for ($nestingIterator = 0; $nestingIterator < $nestingLevel; $nestingIterator++) {
+            $filterByRequestPathCondition[] = $category->getUrlKey();
+            $category = $category->getDataFieldConfig('parent_id')['source']->getParentCategory();
+        }
+
+        return strtolower(implode('/', array_reverse($filterByRequestPathCondition)) . '.html');
+    }
+
+    /**
+     * Retrieve category.
+     *
+     * @param Category $category
+     * @return array
+     */
+    private function retrieveCategory(Category $category)
+    {
+        $childrenIds = explode(',', $this->getResponse($category->getData('parent_id'))['children']);
+        while ($id = array_pop($childrenIds)) {
+            $retrieveCategory = $this->getResponse($id);
+            if ($retrieveCategory['name'] == $category->getData('name')) {
+                return $retrieveCategory;
+            }
+        }
+        return ['id' => null];
+    }
+
+    /**
+     * Return category data by category id.
+     *
+     * @param int $categoryId
+     * @return array
+     */
+    private function getResponse($categoryId)
+    {
+        $url = $_ENV['app_frontend_url'] . 'rest/all/V1/categories/' . $categoryId;
+        $this->webApi->write($url, [], WebapiDecorator::GET);
+        $response = json_decode($this->webApi->read(), true);
+        $this->webApi->close();
+        return $response;
+    }
+
     /**
      * URL rewrite category present in grid.
      *
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteProductInGrid.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteProductInGrid.php
new file mode 100644
index 0000000000000000000000000000000000000000..8277df90cb646208132782a05ad51ea4e4797051
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteProductInGrid.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\UrlRewrite\Test\Constraint;
+
+use Magento\Mtf\Fixture\FixtureInterface;
+use Magento\UrlRewrite\Test\Page\Adminhtml\UrlRewriteIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that url rewrite product in grid.
+ */
+class AssertUrlRewriteProductInGrid extends AbstractConstraint
+{
+    /**
+     * Assert that url rewrite product in grid.
+     *
+     * @param UrlRewriteIndex $urlRewriteIndex
+     * @param FixtureInterface $product
+     * @return void
+     */
+    public function processAssert(
+        UrlRewriteIndex $urlRewriteIndex,
+        FixtureInterface $product
+    ) {
+        $urlRewriteIndex->open();
+        $categories = $product->getDataFieldConfig('category_ids')['source']->getCategories();
+        $rootCategoryArray = [];
+        foreach ($categories as $category) {
+            $parentName = $category->getDataFieldConfig('parent_id')['source']->getParentCategory()->getName();
+            $rootCategoryArray[$parentName] = $category->getUrlKey();
+        }
+
+        $stores = $product->getDataFieldConfig('website_ids')['source']->getStores();
+        foreach ($stores as $store) {
+            $rootCategoryName = $store->getDataFieldConfig('group_id')['source']
+                ->getStoreGroup()
+                ->getDataFieldConfig('root_category_id')['source']
+                ->getCategory()
+                ->getName();
+
+            $storeName = $store->getName();
+            $filters = [
+                [
+                    'request_path' => $product->getUrlKey() . '.html',
+                    'store_id' => $storeName
+                ],
+                [
+                    'request_path' => $rootCategoryArray[$rootCategoryName] . '.html',
+                    'store_id' => $storeName
+                ],
+                [
+                    'request_path' => $rootCategoryArray[$rootCategoryName] . '/' . $product->getUrlKey() . '.html',
+                    'store_id' => $storeName
+                ],
+            ];
+            foreach ($filters as $filter) {
+                \PHPUnit_Framework_Assert::assertTrue(
+                    $urlRewriteIndex->getUrlRedirectGrid()->isRowVisible($filter, true, false),
+                    'URL Rewrite with request path \'' . $filter['request_path'] . '\' is absent in grid.'
+                );
+
+            }
+        }
+    }
+
+    /**
+     * URL rewrite product present in grid.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'URL Rewrite is present in grid.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteProductNotInGrid.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteProductNotInGrid.php
new file mode 100644
index 0000000000000000000000000000000000000000..c32e9925ad0ac54d2bca1d85f52318359c75085a
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteProductNotInGrid.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\UrlRewrite\Test\Constraint;
+
+use Magento\Mtf\Fixture\FixtureInterface;
+use Magento\UrlRewrite\Test\Page\Adminhtml\UrlRewriteIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that url rewrite product not in grid.
+ */
+class AssertUrlRewriteProductNotInGrid extends AbstractConstraint
+{
+    /**
+     * Assert that url rewrite not in grid
+     *
+     * @param UrlRewriteIndex $urlRewriteIndex
+     * @param FixtureInterface $product
+     * @return void
+     */
+    public function processAssert(UrlRewriteIndex $urlRewriteIndex, FixtureInterface $product)
+    {
+        $urlRewriteIndex->open();
+        $requestPath = $product->getUrlKey() . '.html';
+        $filter = ['request_path' => $requestPath];
+        \PHPUnit_Framework_Assert::assertFalse(
+            $urlRewriteIndex->getUrlRedirectGrid()->isRowVisible($filter),
+            'URL Rewrite with request path \'' . $requestPath . '\' is present in grid.'
+        );
+    }
+
+    /**
+     * URL rewrite product not present in grid.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'URL Rewrite is not present in grid.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductUrlRewriteEntityTest.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductUrlRewriteEntityTest.xml
index dc8ba167417e98aeaa1abdba243e1a6f0b2ab922..7153ce42f5fb677e56c887d93da01be64eeef447 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductUrlRewriteEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductUrlRewriteEntityTest.xml
@@ -47,5 +47,15 @@
             <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteSaveMessage" />
             <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteProductRedirect" />
         </variation>
+        <variation name="CreateProductUrlRewriteEntityTestVariation5" summary="Autoupdate URL Rewrites if Subcategories deleted" ticketId="MAGETWO-27325">
+            <data name="urlRewrite/data/entity_type" xsi:type="string">For Product</data>
+            <data name="product/dataset" xsi:type="string">product_with_category</data>
+            <data name="urlRewrite/data/store_id" xsi:type="string">Main Website/Main Website Store/Default Store View</data>
+            <data name="urlRewrite/data/request_path" xsi:type="string">cat%isolation%/simp_redirect%isolation%.html</data>
+            <data name="urlRewrite/data/redirect_type" xsi:type="string">Temporary (302)</data>
+            <data name="urlRewrite/data/description" xsi:type="string">description_%isolation%</data>
+            <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteSaveMessage" />
+            <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteAfterDeletingCategory" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductWithSeveralWebsitesUrlRewriteTest.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductWithSeveralWebsitesUrlRewriteTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2bb0ebe63650265aa63ad8e851070a757418f61c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductWithSeveralWebsitesUrlRewriteTest.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\UrlRewrite\Test\TestCase;
+
+use Magento\Catalog\Test\Fixture\CatalogProductSimple;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew;
+use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Mtf\TestCase\Injectable;
+
+/**
+ * Steps:
+ * 1. Login to the backend.
+ * 2. Navigate to Products > Catalog.
+ * 3. Start to create simple product.
+ * 4. Fill in data according to data set.
+ * 5. Save Product.
+ * 6. Perform appropriate assertions.
+ *
+ * @ZephyrId MAGETWO-27238
+ */
+class CreateProductWithSeveralWebsitesUrlRewriteTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    /* end tags */
+
+    /**
+     * Run create product with several websites url rewrite test.
+     *
+     * @param CatalogProductSimple $product
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductNew $newProductPage
+     * @param FixtureFactory $fixtureFactory
+     * @param array $websiteCategories
+     * @return array
+     */
+    public function testCreate(
+        CatalogProductSimple $product,
+        CatalogProductIndex $productGrid,
+        CatalogProductNew $newProductPage,
+        FixtureFactory $fixtureFactory,
+        array $websiteCategories
+    ) {
+        $categoryParent = [];
+        $categoryList = [];
+        $storeList = [];
+
+        // Preconditions
+        foreach ($websiteCategories as $websiteCategory) {
+            list($storeGroup, $store, $category) = explode('::', $websiteCategory);
+            if (!isset($categoryParent[$category])) {
+                $categoryListItem = $fixtureFactory->createByCode('category', ['dataset' => $category]);
+                $categoryListItem->persist();
+                $categoryParent[$category] = $categoryListItem->getDataFieldConfig('parent_id')['source']
+                    ->getParentCategory();
+                $categoryList[] = $categoryListItem;
+            }
+            $storeGroup = $fixtureFactory->createByCode('storeGroup', [
+                'dataset' => $storeGroup,
+                'data' => [
+                    'root_category_id' => [
+                        'category' => $categoryParent[$category]
+                    ]
+                ]
+            ]);
+            $storeGroup->persist();
+            $store = $fixtureFactory->createByCode('store', [
+                'dataset' => $store,
+                'data' => [
+                    'group_id' => [
+                        'storeGroup' => $storeGroup
+                    ]
+                ]
+            ]);
+            $store->persist();
+            $storeList[] = $store;
+        }
+
+        $productData = $product->getData();
+        $productData['website_ids'] = $storeList;
+        $productData['category_ids'] = $categoryList;
+
+        $product = $fixtureFactory->createByCode(
+            'catalogProductSimple',
+            [
+                'dataset' => 'default',
+                'data' => $productData,
+            ]
+        );
+
+        // Steps
+        $productGrid->open();
+        $productGrid->getGridPageActionBlock()->addProduct('simple');
+        $newProductPage->getProductForm()->fill($product);
+        $newProductPage->getFormPageActions()->save();
+
+        return ['product' => $product];
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductWithSeveralWebsitesUrlRewriteTest.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductWithSeveralWebsitesUrlRewriteTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..afde5d24637ac751f7bc8d599be2e0e9720c114d
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductWithSeveralWebsitesUrlRewriteTest.xml
@@ -0,0 +1,26 @@
+<?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\UrlRewrite\Test\TestCase\CreateProductWithSeveralWebsitesUrlRewriteTest" summary="Test product url rewrites when it is created in several websites">
+        <variation name="CreateSimpleProductEntityWithSeveralWebsites" summary="Create product with several websites and check URL Rewites" ticketId="MAGETWO-27238">
+            <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data>
+            <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data>
+            <data name="product/data/sku" xsi:type="string">simple_sku_%isolation%</data>
+            <data name="product/data/price/value" xsi:type="string">42</data>
+            <data name="product/data/weight" xsi:type="string">50</data>
+            <data name="product/data/quantity_and_stock_status/qty" xsi:type="string">345</data>
+            <data name="websiteCategories" xsi:type="array">
+                <item name="0" xsi:type="string">default::default::default</item>
+                <item name="1" xsi:type="string">store_group_new_1::store_new_1::default</item>
+                <item name="2" xsi:type="string">store_group_new_2::store_new_2::root_subcategory</item>
+            </data>
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" />
+            <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteProductInGrid" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertIncorrectUserPassword.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertIncorrectUserPassword.php
index ffc549a6211913210bf5a2af67425579bdb8e160..62a3c64142949067c18d830411c13054e539b71f 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertIncorrectUserPassword.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertIncorrectUserPassword.php
@@ -6,11 +6,11 @@
 
 namespace Magento\User\Test\Constraint;
 
-use Magento\User\Test\Page\Adminhtml\UserRoleIndex;
+use Magento\Backend\Test\Page\Adminhtml\Dashboard;
 use Magento\Mtf\Constraint\AbstractConstraint;
 
 /**
- * Class AssertIncorrectUserPassword
+ * Assert that message about incorrect user password is displayed.
  */
 class AssertIncorrectUserPassword extends AbstractConstraint
 {
@@ -19,12 +19,12 @@ class AssertIncorrectUserPassword extends AbstractConstraint
     /**
      * Asserts that invalid password message equals to expected message.
      *
-     * @param UserRoleIndex $rolePage
+     * @param Dashboard $dashboard
      * @return void
      */
-    public function processAssert(UserRoleIndex $rolePage)
+    public function processAssert(Dashboard $dashboard)
     {
-        $errorMessage = $rolePage->getMessagesBlock()->getErrorMessage();
+        $errorMessage = $dashboard->getMessagesBlock()->getErrorMessage();
         \PHPUnit_Framework_Assert::assertEquals(
             self::ERROR_MESSAGE,
             $errorMessage,
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Repository/Role.xml b/dev/tests/functional/tests/app/Magento/User/Test/Repository/Role.xml
index 6d256383ba8f874be836671b2cc20e2be4b17e37..6d19e0488c287f8016b3c33ecfdfe4cde807f836 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/Repository/Role.xml
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Repository/Role.xml
@@ -47,5 +47,35 @@
                 <item name="Send Sales Emails" xsi:type="string">Magento_Sales::emails</item>
             </field>
         </dataset>
+
+        <dataset name="role_without_variable">
+            <field name="rolename" xsi:type="string">RoleName%isolation%</field>
+            <field name="resource_access" xsi:type="string">Custom</field>
+            <field name="current_password" xsi:type="string">%current_password%</field>
+            <field name="roles_resources" xsi:type="array">
+                <item name="Dashboard" xsi:type="string">Magento_Backend::dashboard</item>
+                <item name="AdminNotification" xsi:type="string">Magento_AdminNotification::adminnotification</item>
+                <item name="EncryptionKey" xsi:type="string">Magento_EncryptionKey::crypt_key</item>
+                <item name="Content" xsi:type="string">Magento_Backend::content</item>
+                <item name="ContentElements" xsi:type="string">Magento_Backend::content_elements</item>
+                <item name="Page" xsi:type="string">Magento_Cms::page</item>
+                <item name="SavePage" xsi:type="string">Magento_Cms::save</item>
+                <item name="DeletePage" xsi:type="string">Magento_Cms::page_delete</item>
+            </field>
+        </dataset>
+
+        <dataset name="role_without_synonym">
+            <field name="rolename" xsi:type="string">RoleName%isolation%</field>
+            <field name="resource_access" xsi:type="string">Custom</field>
+            <field name="current_password" xsi:type="string">%current_password%</field>
+            <field name="roles_resources" xsi:type="array">
+                <item name="Dashboard" xsi:type="string">Magento_Backend::dashboard</item>
+                <item name="Marketing" xsi:type="string">Magento_Backend::marketing</item>
+                <item name="Seo" xsi:type="string">Magento_Backend::marketing_seo</item>
+                <item name="SearchTerms" xsi:type="string">Magento_Search::search</item>
+                <item name="UrlRewrite" xsi:type="string">Magento_UrlRewrite::urlrewrite</item>
+                <item name="Sitemap" xsi:type="string">Magento_Sitemap::sitemap</item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Repository/User.xml b/dev/tests/functional/tests/app/Magento/User/Test/Repository/User.xml
index dbb7a4aeb53bb667bf22e99e0198d1b0e3cab25c..29c61d931d73090e9f8fd3a0823f66451596d540 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/Repository/User.xml
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Repository/User.xml
@@ -45,5 +45,33 @@
         <dataset name="system_admin">
             <field name="current_password" xsi:type="string">123123q</field>
         </dataset>
+
+        <dataset name="custom_admin_with_role_without_variable">
+            <field name="username" xsi:type="string">AdminUser%isolation%</field>
+            <field name="firstname" xsi:type="string">FirstName%isolation%</field>
+            <field name="lastname" xsi:type="string">LastName%isolation%</field>
+            <field name="email" xsi:type="string">email%isolation%@example.com</field>
+            <field name="password" xsi:type="string">123123q</field>
+            <field name="password_confirmation" xsi:type="string">123123q</field>
+            <field name="role_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">role::role_without_variable</item>
+            </field>
+            <field name="current_password" xsi:type="string">%current_password%</field>
+            <field name="is_active" xsi:type="string">Active</field>
+        </dataset>
+
+        <dataset name="custom_admin_with_role_without_synonym">
+            <field name="username" xsi:type="string">AdminUser%isolation%</field>
+            <field name="firstname" xsi:type="string">FirstName%isolation%</field>
+            <field name="lastname" xsi:type="string">LastName%isolation%</field>
+            <field name="email" xsi:type="string">email%isolation%@example.com</field>
+            <field name="password" xsi:type="string">123123q</field>
+            <field name="password_confirmation" xsi:type="string">123123q</field>
+            <field name="role_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">role::role_without_synonym</item>
+            </field>
+            <field name="current_password" xsi:type="string">%current_password%</field>
+            <field name="is_active" xsi:type="string">Active</field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserEntityTest.php b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserEntityTest.php
index fdf10565117764fa85727d38a4d10c44e4047261..27c38a27df12f1203ee19fb2b1d3bc3ef79efe62 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserEntityTest.php
@@ -91,10 +91,10 @@ class CreateAdminUserEntityTest extends Injectable
      * @param string $isDuplicated
      * @return array
      */
-    public function test(User $user, User $adminUser, $isDuplicated)
+    public function test(User $user, User $adminUser, $isDuplicated = null)
     {
         // Prepare data
-        if ($isDuplicated != '-') {
+        if ($isDuplicated !== null) {
             $data = $user->getData();
             $data[$isDuplicated] = $adminUser->getData($isDuplicated);
             $data['role_id'] = ['role' => $user->getDataFieldConfig('role_id')['source']->getRole()];
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserEntityTest.xml b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserEntityTest.xml
index f2005174d24dbda5791633790519ca1c3a8c4a76..b6c346fea8dfbd66803cf7b1098fe85cce65c43e 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserEntityTest.xml
@@ -17,7 +17,6 @@
             <data name="user/data/password_confirmation" xsi:type="string">123123q</data>
             <data name="user/data/is_active" xsi:type="string">Active</data>
             <data name="user/data/role_id/dataset" xsi:type="string">role::Administrators</data>
-            <data name="isDuplicated" xsi:type="string">-</data>
             <data name="user/data/current_password" xsi:type="string">%current_password%</data>
             <constraint name="Magento\User\Test\Constraint\AssertUserSuccessSaveMessage" />
             <constraint name="Magento\User\Test\Constraint\AssertUserInGrid" />
@@ -33,7 +32,6 @@
             <data name="user/data/password_confirmation" xsi:type="string">123123q</data>
             <data name="user/data/is_active" xsi:type="string">Inactive</data>
             <data name="user/data/role_id/dataset" xsi:type="string">role::Administrators</data>
-            <data name="isDuplicated" xsi:type="string">-</data>
             <data name="user/data/current_password" xsi:type="string">123123q</data>
             <constraint name="Magento\User\Test\Constraint\AssertUserSuccessSaveMessage" />
             <constraint name="Magento\User\Test\Constraint\AssertUserInGrid" />
@@ -72,7 +70,6 @@
             <data name="user/data/password" xsi:type="string">123123q</data>
             <data name="user/data/password_confirmation" xsi:type="string">123123q</data>
             <data name="user/data/is_active" xsi:type="string">Active</data>
-            <data name="isDuplicated" xsi:type="string">-</data>
             <data name="user/data/current_password" xsi:type="string">%current_password%</data>
             <constraint name="Magento\User\Test\Constraint\AssertUserSuccessSaveMessage" />
             <constraint name="Magento\User\Test\Constraint\AssertUserInGrid" />
@@ -87,9 +84,18 @@
             <data name="user/data/password" xsi:type="string">123123q</data>
             <data name="user/data/password_confirmation" xsi:type="string">123123q</data>
             <data name="user/data/is_active" xsi:type="string">Active</data>
-            <data name="isDuplicated" xsi:type="string">-</data>
             <data name="user/data/current_password" xsi:type="string">%current_password%</data>
             <constraint name="Magento\User\Test\Constraint\AssertUserInvalidEmailHostnameMessage" />
         </variation>
+        <variation name="CreateAdminUserWithIncorrectCurrentPassword" summary="Try to create admin user with incorrect current password" ticketId="MAGETWO-49034">
+            <data name="user/data/username" xsi:type="string">AdminUser%isolation%</data>
+            <data name="user/data/firstname" xsi:type="string">FirstName%isolation%</data>
+            <data name="user/data/lastname" xsi:type="string">LastName%isolation%</data>
+            <data name="user/data/email" xsi:type="string">email%isolation%@example.com</data>
+            <data name="user/data/password" xsi:type="string">123123q</data>
+            <data name="user/data/password_confirmation" xsi:type="string">123123q</data>
+            <data name="user/data/current_password" xsi:type="string">incorrect-password</data>
+            <constraint name="Magento\User\Test\Constraint\AssertIncorrectUserPassword" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CustomAclPermissionTest.php b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CustomAclPermissionTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..8378efa6122adade9016a2c42f0fbc1e745a417e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CustomAclPermissionTest.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\User\Test\TestCase;
+
+use Magento\User\Test\Fixture\User;
+use Magento\Mtf\TestCase\Injectable;
+use Magento\Mtf\TestStep\TestStepFactory;
+
+/**
+ * Preconditions:
+ * 1. Create custom admin with custom role.
+ *
+ * Steps:
+ * 1. Login to the admin panel with the newly created admin user.
+ * 2. Perform all assertions.
+ *
+ * @ZephyrId MAGETWO-41214, MAGETWO-58541, MAGETWO-47568
+ */
+class CustomAclPermissionTest extends Injectable
+{
+    /* tags */
+    const MVP = 'no';
+    /* end tags */
+
+    /**
+     * Test step factory.
+     *
+     * @var TestStepFactory
+     */
+    protected $testStepFactory;
+
+    /**
+     * Setup necessary data for test.
+     *
+     * @param TestStepFactory $testStepFactory
+     * @return void
+     */
+    public function __inject(
+        TestStepFactory $testStepFactory
+    ) {
+        $this->testStepFactory = $testStepFactory;
+    }
+
+    /**
+     * Test acl permissions.
+     *
+     * @param User $user
+     * @return array
+     */
+    public function test(User $user)
+    {
+        $user->persist();
+        $this->testStepFactory->create(
+            \Magento\User\Test\TestStep\LoginUserOnBackendStep::class,
+            ['user' => $user]
+        )->run();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Variable/Test/Constraint/AssertCustomVariableRestrictedAccess.php b/dev/tests/functional/tests/app/Magento/Variable/Test/Constraint/AssertCustomVariableRestrictedAccess.php
new file mode 100644
index 0000000000000000000000000000000000000000..cee2e597216a78619be4df109b85fb474cb125d2
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Variable/Test/Constraint/AssertCustomVariableRestrictedAccess.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Variable\Test\Constraint;
+
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Cms\Test\Page\Adminhtml\CmsPageNew;
+use Magento\Variable\Test\Fixture\SystemVariable;
+
+/**
+ * Check that access to variables block on CMS page in admin panel is restricted.
+ */
+class AssertCustomVariableRestrictedAccess extends AbstractConstraint
+{
+    /**
+     * Assert that variables block is not visible.
+     *
+     * @param CmsPageNew $cmsPageNew
+     * @param SystemVariable $systemVariable
+     * @return void
+     */
+    public function processAssert(
+        CmsPageNew $cmsPageNew,
+        SystemVariable $systemVariable
+    ) {
+        $systemVariable->persist();
+        $cmsPageNew->open();
+
+        \PHPUnit_Framework_Assert::assertFalse(
+            $cmsPageNew->getPageForm()->isVariablesBlockVisible(),
+            'Access to system variables block is supposed to be restricted.'
+        );
+    }
+
+    /**
+     * Returns a string representation of successful assertion.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Access to system variables block is restricted and block is not visible.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Variable/Test/TestCase/CustomAclPermissionTest.xml b/dev/tests/functional/tests/app/Magento/Variable/Test/TestCase/CustomAclPermissionTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dd4d623de6325d567c12f8d3aaae40ee017b7c85
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Variable/Test/TestCase/CustomAclPermissionTest.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\User\Test\TestCase\CustomAclPermissionTest" summary="Custom ACL Permission" ticketId="MAGETWO-58541">
+        <variation name="CustomVariableAclPermissionTestVariation1" summary="Custom variable ACL permission" ticketId="MAGETWO-41214">
+            <data name="user/dataset" xsi:type="string">custom_admin_with_role_without_variable</data>
+            <data name="systemVariable/dataset" xsi:type="string">default</data>
+            <constraint name="Magento\Variable\Test\Constraint\AssertCustomVariableRestrictedAccess" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/utils/command.php b/dev/tests/functional/utils/command.php
index 4061b07c783e4b0e8cbf4a7e4daa08d445834f68..a149be72a1ca48fbb7531b74d3dc84b687c5f737 100644
--- a/dev/tests/functional/utils/command.php
+++ b/dev/tests/functional/utils/command.php
@@ -8,5 +8,5 @@ if (isset($_GET['command'])) {
     $command = urldecode($_GET['command']);
     exec('php -f ../../../../bin/magento ' . $command);
 } else {
-    throw new \Exception("Command GET parameter is not set.");
+    throw new \InvalidArgumentException("Command GET parameter is not set.");
 }
diff --git a/dev/tests/functional/utils/export.php b/dev/tests/functional/utils/export.php
new file mode 100644
index 0000000000000000000000000000000000000000..062e8de6cbe7d6453f75d48b4faaf208ebffddc5
--- /dev/null
+++ b/dev/tests/functional/utils/export.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+if (!isset($_GET['template'])) {
+    throw new \InvalidArgumentException('Argument "template" must be set.');
+}
+
+$varDir = '../../../../var/';
+$template = urldecode($_GET['template']);
+$fileList = scandir($varDir, SCANDIR_SORT_NONE);
+$files = [];
+
+foreach ($fileList as $fileName) {
+    if (preg_match("`$template`", $fileName) === 1) {
+        $filePath = $varDir . $fileName;
+        $files[] = [
+            'content' => file_get_contents($filePath),
+            'name' => $fileName,
+            'date' => filectime($filePath),
+        ];
+    }
+}
+
+echo serialize($files);
diff --git a/dev/tests/integration/framework/Magento/TestFramework/Bootstrap/DocBlock.php b/dev/tests/integration/framework/Magento/TestFramework/Bootstrap/DocBlock.php
index bf890b2448e23f7a134574b9fb2fb2d7eca1151e..d23985bc38ef961b6b7881a02cc35b6811012cc8 100644
--- a/dev/tests/integration/framework/Magento/TestFramework/Bootstrap/DocBlock.php
+++ b/dev/tests/integration/framework/Magento/TestFramework/Bootstrap/DocBlock.php
@@ -40,6 +40,7 @@ class DocBlock
      *
      * Note: order of registering (and applying) annotations is important.
      * To allow config fixtures to deal with fixture stores, data fixtures should be processed first.
+     * ConfigFixture applied twice because data fixtures could clean config and clean custom settings
      *
      * @param \Magento\TestFramework\Application $application
      * @return array
@@ -68,6 +69,7 @@ class DocBlock
             new \Magento\TestFramework\Annotation\AppArea($application),
             new \Magento\TestFramework\Annotation\Cache($application),
             new \Magento\TestFramework\Annotation\AdminConfigFixture(),
+            new \Magento\TestFramework\Annotation\ConfigFixture(),
         ];
     }
 }
diff --git a/dev/tests/integration/framework/Magento/TestFramework/ObjectManager.php b/dev/tests/integration/framework/Magento/TestFramework/ObjectManager.php
index ad685845cde004bd54c8499671e9e22faa72d0e5..03fb9aa9ddae60d356158905a412500f12f8b616 100644
--- a/dev/tests/integration/framework/Magento/TestFramework/ObjectManager.php
+++ b/dev/tests/integration/framework/Magento/TestFramework/ObjectManager.php
@@ -24,8 +24,6 @@ class ObjectManager extends \Magento\Framework\App\ObjectManager
      * @var array
      */
     protected $persistedInstances = [
-        \Magento\TestFramework\App\Config::class,
-        \Magento\Framework\App\Config\ScopeConfigInterface::class,
         \Magento\Framework\App\ResourceConnection::class,
         \Magento\Framework\Config\Scope::class,
         \Magento\Framework\ObjectManager\RelationsInterface::class,
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Helper/DataTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Helper/DataTest.php
index 071c2499bb33262f1f1df9a6bcbd1f37340516ed..c2db58728d33d426a2e87736a8bbd76f212b1e91 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Helper/DataTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Helper/DataTest.php
@@ -248,6 +248,7 @@ class DataTest extends \PHPUnit_Framework_TestCase
      * @magentoDataFixture Magento/Customer/_files/customer.php
      * @magentoDataFixture Magento/Customer/_files/customer_address.php
      * @magentoDbIsolation enabled
+     * @magentoAppIsolation enabled
      * @dataProvider getTaxPriceDataProvider
      */
     public function testGetTaxPrice(
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_two_websites.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_two_websites.php
index fa64de38e43114d74389f2c4ee27a3e0c0b7606d..426ee922f261426758e1ea2361ecf1d4716e9cb9 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_two_websites.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_two_websites.php
@@ -9,25 +9,23 @@ use Magento\Catalog\Api\Data\ProductInterface;
 $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
 /** @var Magento\Store\Model\Website $website */
 $website = $objectManager->get(Magento\Store\Model\Website::class);
-$website->load('second_website', 'code');
 
-if (!$website->getId()) {
-    $website->setData(
-        [
-            'code' => 'second_website',
-            'name' => 'Test Website',
-        ]
-    );
+$website->setData(
+    [
+        'code' => 'second_website',
+        'name' => 'Test Website',
+    ]
+);
 
-    $website->save();
-}
+$website->save();
+
+$objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->reinitStores();
 
 /** @var $product \Magento\Catalog\Model\Product */
 $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
     ->create(ProductInterface::class);
 $product
     ->setTypeId('simple')
-    ->setId(1)
     ->setAttributeSetId(4)
     ->setWebsiteIds([1, $website->getId()])
     ->setName('Simple Product')
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_two_websites_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_two_websites_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..68f1106dcfe3098041c58726d72f2d7f949ddaea
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_two_websites_rollback.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+use Magento\Catalog\Api\Data\ProductInterface;
+
+$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+
+/** @var \Magento\Framework\Registry $registry */
+$registry = $objectManager
+    ->get(\Magento\Framework\Registry::class);
+$registry->unregister("isSecureArea");
+$registry->register("isSecureArea", true);
+
+/** @var Magento\Store\Model\Website $website */
+$website = $objectManager->create(\Magento\Store\Model\Website::class);
+$website->load('second_website');
+$website->delete();
+
+/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */
+$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+
+try {
+    $firstProduct = $productRepository->get('unique-simple-azaza');
+    $firstProduct->delete();
+} catch (\Magento\Framework\Exception\NoSuchEntityException $exception) {
+    //Product already removed
+}
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', false);
+
+$objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->reinitStores();
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/second_website.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/second_website.php
index 6749d421e79981f0b3b917f21b975c9ad2c74e26..4dc026d6fad4d58a3533653bc0bc4cb070683313 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/_files/second_website.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/second_website.php
@@ -19,3 +19,5 @@ if (!$website->getId()) {
 
     $website->save();
 }
+
+$objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->reinitStores();
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/second_website_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/second_website_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..173793a1caa49bbc772916f23d6e24c2e6c87342
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/second_website_rollback.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry');
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', true);
+
+$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+$website = $objectManager->get(Magento\Store\Model\Website::class);
+$website->load('test_website', 'code');
+
+if ($website->getId()) {
+    $website->delete();
+}
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', false);
+
+$objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->reinitStores();
diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/IndexSwitcherMock.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/IndexSwitcherMock.php
new file mode 100644
index 0000000000000000000000000000000000000000..955ccce3bb59e5fc5b23ed57dbf917941ace1eb7
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/IndexSwitcherMock.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogSearch\Model\Indexer;
+
+
+use Magento\CatalogSearch\Model\Indexer\IndexSwitcherInterface;
+
+/**
+ * The proxy class around index switcher which allows to ensure that the IndexSwitcher was actually used
+ */
+class IndexSwitcherMock extends \PHPUnit_Framework_Assert implements IndexSwitcherInterface
+{
+    private $isSwitched = false;
+
+    /**
+     * @var \Magento\CatalogSearch\Model\Indexer\IndexSwitcherInterface
+     */
+    private $indexSwitcher;
+
+    /**
+     * @param \Magento\CatalogSearch\Model\Indexer\IndexSwitcherInterface $indexSwitcher
+     */
+    public function __construct(
+        IndexSwitcherInterface $indexSwitcher
+    ) {
+        $this->indexSwitcher = $indexSwitcher;
+    }
+
+    /**
+     * Switch current index with temporary index
+     *
+     * It will drop current index table and rename temporary index table to the current index table.
+     *
+     * @param array $dimensions
+     * @return void
+     */
+    public function switchIndex(array $dimensions)
+    {
+        $this->isSwitched |= true;
+        $this->indexSwitcher->switchIndex($dimensions);
+    }
+
+    /**
+     * @return bool
+     */
+    public function isSwitched()
+    {
+        return (bool) $this->isSwitched;
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/SwitcherUsedInFulltextTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/SwitcherUsedInFulltextTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..afcfef5fc4c8e085549c46568d47aa45041b7a6a
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/SwitcherUsedInFulltextTest.php
@@ -0,0 +1,214 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\CatalogSearch\Model\Indexer;
+
+use Magento\Catalog\Model\Product;
+use Magento\CatalogSearch\Model\Indexer\Fulltext;
+use Magento\CatalogSearch\Model\Indexer\IndexSwitcherMock;
+use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection;
+use Magento\TestFramework\Helper\Bootstrap;
+
+/**
+ * @magentoDbIsolation disabled
+ * @magentoDataFixture Magento/CatalogSearch/_files/indexer_fulltext.php
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class SwitcherUsedInFulltextTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var IndexSwitcherInterface
+     */
+    private $indexSwitcher;
+
+    /**
+     * @var \Magento\Framework\Indexer\IndexerInterface
+     */
+    protected $indexer;
+
+    /**
+     * @var \Magento\CatalogSearch\Model\ResourceModel\Engine
+     */
+    protected $engine;
+
+    /**
+     * @var \Magento\CatalogSearch\Model\ResourceModel\Fulltext
+     */
+    protected $resourceFulltext;
+
+    /**
+     * @var \Magento\CatalogSearch\Model\Fulltext
+     */
+    protected $fulltext;
+
+    /**
+     * @var \Magento\Search\Model\QueryFactory
+     */
+    protected $queryFactory;
+
+    /**
+     * @var \Magento\Catalog\Model\Product
+     */
+    protected $productApple;
+
+    /**
+     * @var \Magento\Catalog\Model\Product
+     */
+    protected $productBanana;
+
+    /**
+     * @var \Magento\Catalog\Model\Product
+     */
+    protected $productOrange;
+
+    /**
+     * @var \Magento\Catalog\Model\Product
+     */
+    protected $productPapaya;
+
+    /**
+     * @var \Magento\Catalog\Model\Product
+     */
+    protected $productCherry;
+
+    /**
+     * @var  \Magento\Framework\Search\Request\Dimension
+     */
+    protected $dimension;
+
+    protected function setUp()
+    {
+        $objectManager = Bootstrap::getObjectManager();
+
+        $objectManager->configure(
+            [
+                ltrim(Fulltext::class, '\\') => [
+                    'arguments' => [
+                        'indexSwitcher' => [
+                            'instance' => ltrim(IndexSwitcherMock::class, '\\'),
+                        ],
+                    ],
+                ],
+            ]
+        );
+
+        /** @var \Magento\Framework\Indexer\IndexerInterface indexer */
+        $this->indexer = $objectManager->create(
+            \Magento\Indexer\Model\Indexer::class
+        );
+        $this->indexer->load('catalogsearch_fulltext');
+
+        $this->engine = $objectManager->get(
+            \Magento\CatalogSearch\Model\ResourceModel\Engine::class
+        );
+
+        $this->resourceFulltext = $objectManager->get(
+            \Magento\CatalogSearch\Model\ResourceModel\Fulltext::class
+        );
+
+        $this->queryFactory = $objectManager->get(
+            \Magento\Search\Model\QueryFactory::class
+        );
+
+        $this->dimension = $objectManager->create(
+            \Magento\Framework\Search\Request\Dimension::class,
+            ['name' => 'scope', 'value' => '1']
+        );
+
+        $this->indexSwitcher = Bootstrap::getObjectManager()->get(
+            IndexSwitcherMock::class
+        );
+
+        $this->productApple = $this->getProductBySku('fulltext-1');
+        $this->productBanana = $this->getProductBySku('fulltext-2');
+        $this->productOrange = $this->getProductBySku('fulltext-3');
+        $this->productPapaya = $this->getProductBySku('fulltext-4');
+        $this->productCherry = $this->getProductBySku('fulltext-5');
+    }
+
+    /**
+     * @magentoAppIsolation enabled
+     */
+    public function testReindexAll()
+    {
+        $this->indexer->reindexAll();
+
+        /** @var IndexSwitcherMock $indexSwitcher */
+        $indexSwitcher = Bootstrap::getObjectManager()->get(
+            IndexSwitcherMock::class
+        );
+        $this->assertTrue($indexSwitcher->isSwitched());
+    }
+
+    /**
+     * @magentoAppIsolation enabled
+     */
+    public function testReindexList()
+    {
+        $this->indexer->reindexList([$this->productApple->getId(), $this->productBanana->getId()]);
+
+        /** @var IndexSwitcherMock $indexSwitcher */
+        $indexSwitcher = Bootstrap::getObjectManager()->get(
+            IndexSwitcherMock::class
+        );
+        $this->assertFalse($indexSwitcher->isSwitched());
+    }
+
+    /**
+     * @magentoAppIsolation enabled
+     */
+    public function testReindexRow()
+    {
+        $this->indexer->reindexRow($this->productPapaya->getId());
+
+        /** @var IndexSwitcherMock $indexSwitcher */
+        $indexSwitcher = Bootstrap::getObjectManager()->get(
+            IndexSwitcherMock::class
+        );
+        $this->assertFalse($indexSwitcher->isSwitched());
+    }
+
+    /**
+     * Search the text and return result collection
+     *
+     * @param string $text
+     * @return Product[]
+     */
+    protected function search($text)
+    {
+        $this->resourceFulltext->resetSearchResults();
+        $query = $this->queryFactory->get();
+        $query->unsetData();
+        $query->setQueryText($text);
+        $query->saveIncrementalPopularity();
+        $products = [];
+        $collection = Bootstrap::getObjectManager()->create(
+            Collection::class,
+            [
+                'searchRequestName' => 'quick_search_container'
+            ]
+        );
+        $collection->addSearchFilter($text);
+        foreach ($collection as $product) {
+            $products[] = $product;
+        }
+        return $products;
+    }
+
+    /**
+     * Return product by SKU
+     *
+     * @param string $sku
+     * @return Product
+     */
+    protected function getProductBySku($sku)
+    {
+        /** @var Product $product */
+        $product = Bootstrap::getObjectManager()->get(
+            \Magento\Catalog\Model\Product::class
+        );
+        return $product->loadByAttribute('sku', $sku);
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php
index 67a6e416973493887912e2e62674108b1694c315..7f50638f469de0f8a5c392f97c74094582a432b9 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php
@@ -331,6 +331,10 @@ class AdapterTest extends \PHPUnit_Framework_TestCase
      *
      * @magentoConfigFixture current_store catalog/search/engine mysql
      * @dataProvider advancedSearchDataProvider
+     * @param string $nameQuery
+     * @param string $descriptionQuery
+     * @param array $rangeFilter
+     * @param int $expectedRecordsCount
      */
     public function testSimpleAdvancedSearch(
         $nameQuery,
@@ -445,6 +449,37 @@ class AdapterTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals(1, $queryResponse->count());
     }
 
+    /**
+     * @magentoDataFixture Magento/Framework/Search/_files/product_configurable_with_disabled_child.php
+     * @magentoConfigFixture current_store catalog/search/engine mysql
+     */
+    public function testAdvancedSearchCompositeProductWithDisabledChild()
+    {
+        /** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute */
+        $attribute = $this->objectManager->get(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class)
+            ->loadByCode(\Magento\Catalog\Model\Product::ENTITY, 'test_configurable');
+        /** @var \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection $selectOptions */
+        $selectOptions = $this->objectManager
+            ->create(\Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection::class)
+            ->setAttributeFilter($attribute->getId());
+
+        $firstOption = $selectOptions->getFirstItem();
+        $firstOptionId = $firstOption->getId();
+        $this->requestBuilder->bind('test_configurable', $firstOptionId);
+        $this->requestBuilder->setRequestName('filter_out_of_stock_child');
+
+        $queryResponse = $this->executeQuery();
+        $this->assertEquals(0, $queryResponse->count());
+
+        $secondOption = $selectOptions->getLastItem();
+        $secondOptionId = $secondOption->getId();
+        $this->requestBuilder->bind('test_configurable', $secondOptionId);
+        $this->requestBuilder->setRequestName('filter_out_of_stock_child');
+
+        $queryResponse = $this->executeQuery();
+        $this->assertEquals(0, $queryResponse->count());
+    }
+
     public function dateDataProvider()
     {
         return [
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable.php
index 590f3c8041c6d819fafa14ef7ddc4d1f2ebccbeb..37b8731fc1d4c377ffc26a16be2d4100997f7247 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable.php
@@ -15,7 +15,7 @@ use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
 use Magento\Eav\Api\Data\AttributeOptionInterface;
 use Magento\TestFramework\Helper\Bootstrap;
 
-\Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize();
+Bootstrap::getInstance()->reinitialize();
 
 require __DIR__ . '/configurable_attribute.php';
 
@@ -33,7 +33,7 @@ $options = $attribute->getOptions();
 $attributeValues = [];
 $attributeSetId = $installer->getAttributeSetId('catalog_product', 'Default');
 $associatedProductIds = [];
-$productIds = [10, 20];
+$productIds = [1010, 1020];
 array_shift($options); //remove the first option which is empty
 
 $isFirstOption = true;
@@ -108,29 +108,8 @@ $extensionConfigurableAttributes->setConfigurableProductLinks($associatedProduct
 
 $product->setExtensionAttributes($extensionConfigurableAttributes);
 
-// Remove any previously created product with the same id.
-/** @var \Magento\Framework\Registry $registry */
-$registry = Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class);
-$registry->unregister('isSecureArea');
-$registry->register('isSecureArea', true);
-try {
-    $productToDelete = $productRepository->getById(1);
-    $productRepository->delete($productToDelete);
-
-    /** @var \Magento\Quote\Model\ResourceModel\Quote\Item $itemResource */
-    $itemResource = Bootstrap::getObjectManager()->get(\Magento\Quote\Model\ResourceModel\Quote\Item::class);
-    $itemResource->getConnection()->delete(
-        $itemResource->getMainTable(),
-        'product_id = ' . $productToDelete->getId()
-    );
-} catch (\Exception $e) {
-    // Nothing to remove
-}
-$registry->unregister('isSecureArea');
-$registry->register('isSecureArea', false);
-
 $product->setTypeId(Configurable::TYPE_CODE)
-    ->setId(1)
+    ->setId(1001)
     ->setAttributeSetId($attributeSetId)
     ->setWebsiteIds([1])
     ->setName('Configurable Product')
@@ -140,8 +119,3 @@ $product->setTypeId(Configurable::TYPE_CODE)
     ->setStockData(['use_config_manage_stock' => 1, 'is_in_stock' => 1]);
 
 $productRepository->save($product);
-//
-///** @var \Magento\Catalog\Model\Indexer\Product\Eav\Processor $eavIndexer */
-//$eavIndexer = Bootstrap::getObjectManager()
-//    ->get(\Magento\Catalog\Model\Indexer\Product\Eav\Processor::class);
-//$eavIndexer->reindexAll();
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_rollback.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_rollback.php
index 8ba4e3abe21cc14a75a66270d22ea262dffeb788..cc585d177aedb9201faafcdef8bd57d5ea6dec73 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_rollback.php
@@ -16,7 +16,7 @@ $registry->register('isSecureArea', true);
 $productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
     ->get(\Magento\Catalog\Api\ProductRepositoryInterface::class);
 
-foreach (['simple_10', 'simple_20', 'configurable'] as $sku) {
+foreach (['simple_1010', 'simple_1020', 'configurable'] as $sku) {
     try {
         $product = $productRepository->get($sku, false, null, true);
 
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_with_disabled_child.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_with_disabled_child.php
new file mode 100644
index 0000000000000000000000000000000000000000..39c9782ba712a7ed2204a61bdcd549863e202ed8
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_with_disabled_child.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+use Magento\Catalog\Api\ProductRepositoryInterface;
+use Magento\TestFramework\Helper\Bootstrap;
+
+require __DIR__ . '/product_configurable.php';
+
+/** @var ProductRepositoryInterface $productRepository */
+$productRepository = Bootstrap::getObjectManager()
+    ->create(ProductRepositoryInterface::class);
+
+$product = $productRepository->get('simple_1020');
+$product->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED);
+$productRepository->save($product);
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_with_disabled_child_rollback.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_with_disabled_child_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..58d1dcd79acde15c2d493625ca38c656ad286bb7
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_with_disabled_child_rollback.php
@@ -0,0 +1,7 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+require __DIR__ . '/product_configurable_rollback.php';
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php
index c64500fa6cfec3aed4a33cbcbc262befa1621d5c..c2bc02893e042de06cce4023d943110a693aeeca 100644
--- a/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php
+++ b/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php
@@ -34,7 +34,7 @@ class CheckoutTest extends \PHPUnit_Framework_TestCase
     /**
      * Verify that an order placed with an existing customer can re-use the customer addresses.
      *
-     * @magentoDataFixture Magento/Paypal/_files/quote_payment_express_with_customer.php
+     * @magentoDataFixture Magento/Paypal/_files/quote_express_with_customer.php
      * @magentoAppIsolation enabled
      * @magentoDbIsolation enabled
      */
@@ -74,7 +74,7 @@ class CheckoutTest extends \PHPUnit_Framework_TestCase
     /**
      * Verify that after placing the order, addresses are associated with the order and the quote is a guest quote.
      *
-     * @magentoDataFixture Magento/Paypal/_files/quote_payment_express.php
+     * @magentoDataFixture Magento/Paypal/_files/quote_express.php
      * @magentoAppIsolation enabled
      * @magentoDbIsolation enabled
      */
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express.php
new file mode 100644
index 0000000000000000000000000000000000000000..0be18cdcaf9e42e2beb792596d0819b3c7a46182
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+\Magento\TestFramework\Helper\Bootstrap::getInstance()->loadArea('adminhtml');
+\Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
+    \Magento\Framework\App\Config\MutableScopeConfigInterface::class
+)->setValue(
+    'carriers/flatrate/active',
+    1,
+    \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+);
+\Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
+    \Magento\Framework\App\Config\MutableScopeConfigInterface::class
+)->setValue(
+    'payment/paypal_express/active',
+    1,
+    \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+);
+$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+/** @var $product \Magento\Catalog\Model\Product */
+$product = $objectManager->create(\Magento\Catalog\Model\Product::class);
+$product->setTypeId('simple')
+    ->setId(1)
+    ->setAttributeSetId(4)
+    ->setName('Simple Product')
+    ->setSku('simple')
+    ->setPrice(10)
+    ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
+    ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
+    ->setStockData(
+        [
+            'qty' => 100,
+            'is_in_stock' => 1,
+        ]
+    )->save();
+$product->load(1);
+
+$billingData = [
+    'firstname' => 'testname',
+    'lastname' => 'lastname',
+    'company' => '',
+    'email' => 'test@com.com',
+    'street' => [
+        0 => 'test1',
+        1 => '',
+    ],
+    'city' => 'Test',
+    'region_id' => '1',
+    'region' => '',
+    'postcode' => '9001',
+    'country_id' => 'US',
+    'telephone' => '11111111',
+    'fax' => '',
+    'confirm_password' => '',
+    'save_in_address_book' => '1',
+    'use_for_shipping' => '1',
+];
+
+$billingAddress = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
+    ->create(\Magento\Quote\Model\Quote\Address::class, ['data' => $billingData]);
+$billingAddress->setAddressType('billing');
+
+$shippingAddress = clone $billingAddress;
+$shippingAddress->setId(null)->setAddressType('shipping');
+$shippingAddress->setShippingMethod('flatrate_flatrate');
+$shippingAddress->setCollectShippingRates(true);
+
+/** @var $quote \Magento\Quote\Model\Quote */
+$quote = $objectManager->create(\Magento\Quote\Model\Quote::class);
+$quote->setCustomerIsGuest(
+    true
+)->setStoreId(
+    $objectManager->get(
+        \Magento\Store\Model\StoreManagerInterface::class
+    )->getStore()->getId()
+)->setReservedOrderId(
+    '100000002'
+)->setBillingAddress(
+    $billingAddress
+)->setShippingAddress(
+    $shippingAddress
+)->addProduct(
+    $product,
+    10
+);
+$quote->getShippingAddress()->setShippingMethod('flatrate_flatrate');
+$quote->getShippingAddress()->setCollectShippingRates(true);
+$quote->getPayment()->setMethod(\Magento\Paypal\Model\Config::METHOD_WPS_EXPRESS);
+
+$quoteRepository = $objectManager->get(\Magento\Quote\Api\CartRepositoryInterface::class);
+$quoteRepository->save($quote);
+$quote = $quoteRepository->get($quote->getId());
+$quote->setCustomerEmail('admin@example.com');
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express_with_customer.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express_with_customer.php
new file mode 100644
index 0000000000000000000000000000000000000000..c319e298d1e50d56cdc886dd789d6c36941e8a4e
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express_with_customer.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+require __DIR__ . '/../../Customer/_files/customer.php';
+require __DIR__ . '/../../Customer/_files/customer_two_addresses.php';
+
+\Magento\TestFramework\Helper\Bootstrap::getInstance()->loadArea('adminhtml');
+
+$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+
+$objectManager->get(
+    \Magento\Framework\App\Config\MutableScopeConfigInterface::class
+)->setValue('carriers/flatrate/active', 1, \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
+$objectManager->get(\Magento\Framework\App\Config\MutableScopeConfigInterface::class)
+    ->setValue('payment/paypal_express/active', 1, \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
+
+/** @var \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository */
+$customerRepository = $objectManager->create(\Magento\Customer\Api\CustomerRepositoryInterface::class);
+$customer = $customerRepository->getById(1);
+
+/** @var $product \Magento\Catalog\Model\Product */
+$product = $objectManager->create(\Magento\Catalog\Model\Product::class);
+$product->setTypeId('simple')
+    ->setId(1)
+    ->setAttributeSetId(4)
+    ->setName('Simple Product')
+    ->setSku('simple')
+    ->setPrice(10)
+    ->setStockData([
+        'use_config_manage_stock' => 1,
+        'qty' => 100,
+        'is_qty_decimal' => 0,
+        'is_in_stock' => 100,
+    ])
+    ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
+    ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
+    ->save();
+$product->load(1);
+
+$customerBillingAddress = $objectManager->create(\Magento\Customer\Model\Address::class);
+$customerBillingAddress->load(1);
+$billingAddressDataObject = $customerBillingAddress->getDataModel();
+$billingAddress = $objectManager->create(\Magento\Quote\Model\Quote\Address::class);
+$billingAddress->importCustomerAddressData($billingAddressDataObject);
+$billingAddress->setAddressType('billing');
+
+/** @var \Magento\Customer\Model\Address $customerShippingAddress */
+$customerShippingAddress = $objectManager->create(\Magento\Customer\Model\Address::class);
+$customerShippingAddress->load(2);
+$shippingAddressDataObject = $customerShippingAddress->getDataModel();
+$shippingAddress = $objectManager->create(\Magento\Quote\Model\Quote\Address::class);
+$shippingAddress->importCustomerAddressData($shippingAddressDataObject);
+$shippingAddress->setAddressType('shipping');
+
+$shippingAddress->setShippingMethod('flatrate_flatrate');
+$shippingAddress->setCollectShippingRates(true);
+
+/** @var $quote \Magento\Quote\Model\Quote */
+$quote = $objectManager->create(\Magento\Quote\Model\Quote::class);
+$quote->setCustomerIsGuest(false)
+    ->setCustomerId($customer->getId())
+    ->setCustomer($customer)
+    ->setStoreId($objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->getStore()->getId())
+    ->setReservedOrderId('test02')
+    ->setBillingAddress($billingAddress)
+    ->setShippingAddress($shippingAddress)
+    ->addProduct($product, 10);
+$quote->getShippingAddress()->setShippingMethod('flatrate_flatrate');
+$quote->getShippingAddress()->setCollectShippingRates(true);
+$quote->getPayment()->setMethod(\Magento\Paypal\Model\Config::METHOD_WPS_EXPRESS);
+
+/** @var \Magento\Quote\Api\CartRepositoryInterface $quoteRepository */
+$quoteRepository = $objectManager->create(\Magento\Quote\Api\CartRepositoryInterface::class);
+$quoteRepository->save($quote);
+$quote = $quoteRepository->get($quote->getId());
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php
index fa234cc444a0730a580d35400483c0f2ee92e416..90f1102e0ec7639910c83dd76d37d0b0e36eef25 100644
--- a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php
+++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php
@@ -3,96 +3,7 @@
  * Copyright © 2016 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-\Magento\TestFramework\Helper\Bootstrap::getInstance()->loadArea('adminhtml');
-\Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-    \Magento\Framework\App\Config\MutableScopeConfigInterface::class
-)->setValue(
-    'carriers/flatrate/active',
-    1,
-    \Magento\Store\Model\ScopeInterface::SCOPE_STORE
-);
-\Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-    \Magento\Framework\App\Config\MutableScopeConfigInterface::class
-)->setValue(
-    'payment/paypal_express/active',
-    1,
-    \Magento\Store\Model\ScopeInterface::SCOPE_STORE
-);
-$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-/** @var $product \Magento\Catalog\Model\Product */
-$product = $objectManager->create(\Magento\Catalog\Model\Product::class);
-$product->setTypeId('simple')
-    ->setId(1)
-    ->setAttributeSetId(4)
-    ->setName('Simple Product')
-    ->setSku('simple')
-    ->setPrice(10)
-    ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
-    ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
-    ->setStockData(
-        [
-            'qty' => 100,
-            'is_in_stock' => 1,
-        ]
-    )->save();
-$product->load(1);
-
-$billingData = [
-    'firstname' => 'testname',
-    'lastname' => 'lastname',
-    'company' => '',
-    'email' => 'test@com.com',
-    'street' => [
-        0 => 'test1',
-        1 => '',
-    ],
-    'city' => 'Test',
-    'region_id' => '1',
-    'region' => '',
-    'postcode' => '9001',
-    'country_id' => 'US',
-    'telephone' => '11111111',
-    'fax' => '',
-    'confirm_password' => '',
-    'save_in_address_book' => '1',
-    'use_for_shipping' => '1',
-];
-
-$billingAddress = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
-    ->create(\Magento\Quote\Model\Quote\Address::class, ['data' => $billingData]);
-$billingAddress->setAddressType('billing');
-
-$shippingAddress = clone $billingAddress;
-$shippingAddress->setId(null)->setAddressType('shipping');
-$shippingAddress->setShippingMethod('flatrate_flatrate');
-$shippingAddress->setCollectShippingRates(true);
-
-/** @var $quote \Magento\Quote\Model\Quote */
-$quote = $objectManager->create(\Magento\Quote\Model\Quote::class);
-$quote->setCustomerIsGuest(
-    true
-)->setStoreId(
-    $objectManager->get(
-        \Magento\Store\Model\StoreManagerInterface::class
-    )->getStore()->getId()
-)->setReservedOrderId(
-    '100000002'
-)->setBillingAddress(
-    $billingAddress
-)->setShippingAddress(
-    $shippingAddress
-)->addProduct(
-    $product,
-    10
-);
-$quote->getShippingAddress()->setShippingMethod('flatrate_flatrate');
-$quote->getShippingAddress()->setCollectShippingRates(true);
-$quote->getPayment()->setMethod(\Magento\Paypal\Model\Config::METHOD_WPS_EXPRESS);
-
-$quoteRepository = $objectManager->get(\Magento\Quote\Api\CartRepositoryInterface::class);
-$quoteRepository->save($quote);
-$quote = $quoteRepository->get($quote->getId());
-$quote->setCustomerEmail('admin@example.com');
+require __DIR__ . '/quote_express.php';
 
 /** @var $service \Magento\Quote\Api\CartManagementInterface */
 $service = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express_with_customer.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express_with_customer.php
index 1c6793f05dea95644067521332900cc647a3648e..eaf444be13367f8769d28e34245c007122b79bf1 100644
--- a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express_with_customer.php
+++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express_with_customer.php
@@ -3,79 +3,7 @@
  * Copyright © 2016 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-
-require __DIR__ . '/../../Customer/_files/customer.php';
-require __DIR__ . '/../../Customer/_files/customer_two_addresses.php';
-
-\Magento\TestFramework\Helper\Bootstrap::getInstance()->loadArea('adminhtml');
-
-$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-
-$objectManager->get(
-    \Magento\Framework\App\Config\MutableScopeConfigInterface::class
-)->setValue('carriers/flatrate/active', 1, \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
-$objectManager->get(\Magento\Framework\App\Config\MutableScopeConfigInterface::class)
-    ->setValue('payment/paypal_express/active', 1, \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
-
-/** @var \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository */
-$customerRepository = $objectManager->create(\Magento\Customer\Api\CustomerRepositoryInterface::class);
-$customer = $customerRepository->getById(1);
-
-/** @var $product \Magento\Catalog\Model\Product */
-$product = $objectManager->create(\Magento\Catalog\Model\Product::class);
-$product->setTypeId('simple')
-    ->setId(1)
-    ->setAttributeSetId(4)
-    ->setName('Simple Product')
-    ->setSku('simple')
-    ->setPrice(10)
-    ->setStockData([
-    'use_config_manage_stock' => 1,
-    'qty' => 100,
-    'is_qty_decimal' => 0,
-    'is_in_stock' => 100,
-])
-    ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
-    ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
-    ->save();
-$product->load(1);
-
-$customerBillingAddress = $objectManager->create(\Magento\Customer\Model\Address::class);
-$customerBillingAddress->load(1);
-$billingAddressDataObject = $customerBillingAddress->getDataModel();
-$billingAddress = $objectManager->create(\Magento\Quote\Model\Quote\Address::class);
-$billingAddress->importCustomerAddressData($billingAddressDataObject);
-$billingAddress->setAddressType('billing');
-
-/** @var \Magento\Customer\Model\Address $customerShippingAddress */
-$customerShippingAddress = $objectManager->create(\Magento\Customer\Model\Address::class);
-$customerShippingAddress->load(2);
-$shippingAddressDataObject = $customerShippingAddress->getDataModel();
-$shippingAddress = $objectManager->create(\Magento\Quote\Model\Quote\Address::class);
-$shippingAddress->importCustomerAddressData($shippingAddressDataObject);
-$shippingAddress->setAddressType('shipping');
-
-$shippingAddress->setShippingMethod('flatrate_flatrate');
-$shippingAddress->setCollectShippingRates(true);
-
-/** @var $quote \Magento\Quote\Model\Quote */
-$quote = $objectManager->create(\Magento\Quote\Model\Quote::class);
-$quote->setCustomerIsGuest(false)
-    ->setCustomerId($customer->getId())
-    ->setCustomer($customer)
-    ->setStoreId($objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->getStore()->getId())
-    ->setReservedOrderId('test02')
-    ->setBillingAddress($billingAddress)
-    ->setShippingAddress($shippingAddress)
-    ->addProduct($product, 10);
-$quote->getShippingAddress()->setShippingMethod('flatrate_flatrate');
-$quote->getShippingAddress()->setCollectShippingRates(true);
-$quote->getPayment()->setMethod(\Magento\Paypal\Model\Config::METHOD_WPS_EXPRESS);
-
-/** @var \Magento\Quote\Api\CartRepositoryInterface $quoteRepository */
-$quoteRepository = $objectManager->create(\Magento\Quote\Api\CartRepositoryInterface::class);
-$quoteRepository->save($quote);
-$quote = $quoteRepository->get($quote->getId());
+require __DIR__ . '/quote_express_with_customer.php';
 
 /** @var $service \Magento\Quote\Api\CartManagementInterface */
 $service = $objectManager->create(\Magento\Quote\Api\CartManagementInterface::class);
diff --git a/dev/tests/js/jasmine/require.conf.js b/dev/tests/js/jasmine/require.conf.js
index 9ba59b81bc27f5326673e59270917b232643ee24..c60ec02943b5ba86a0c7622bf64ce1c037351805 100644
--- a/dev/tests/js/jasmine/require.conf.js
+++ b/dev/tests/js/jasmine/require.conf.js
@@ -16,7 +16,13 @@ require.config({
         ]
     },
     paths: {
-        'tests': 'dev/tests/js/jasmine'
+        'tests': 'dev/tests/js/jasmine',
+        'squire': 'node_modules/squirejs/src/Squire'
+    },
+    shim: {
+        squire: {
+            exports: 'squire'
+        }
     },
     config: {
         jsbuild: {
diff --git a/dev/tests/js/jasmine/spec_runner/settings.json b/dev/tests/js/jasmine/spec_runner/settings.json
index 109da479146da84882c4a6a68e8778db0b19701d..25407123c1f34d66c70c4406d9341f4659f7519b 100644
--- a/dev/tests/js/jasmine/spec_runner/settings.json
+++ b/dev/tests/js/jasmine/spec_runner/settings.json
@@ -57,7 +57,8 @@
             "^\/_SpecRunner.html",
             "^\/dev\/tests",
             "^\/.grunt",
-            "^\/pub\/static"
+            "^\/pub\/static",
+            "^\/node_modules"
         ],
         "options": {
             /**
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/model/new-customer-address.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/model/new-customer-address.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..ae7ff3d145e2b0ae8c2850ff8d2217baa9fed3f1
--- /dev/null
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/model/new-customer-address.test.js
@@ -0,0 +1,74 @@
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+define([
+    'Magento_Checkout/js/model/new-customer-address'
+], function (NewCustomerAddress) {
+    'use strict';
+
+    describe('Magento_Checkout/js/model/new-customer-address', function () {
+        var newCustomerAddress;
+
+        window.checkoutConfig = {
+            defaultCountryId: 'US'
+        };
+
+        beforeEach(function () {
+            newCustomerAddress = NewCustomerAddress;
+        });
+
+        it('Check that is executable.', function () {
+            expect(typeof newCustomerAddress).toEqual('function');
+        });
+
+        it('Check on empty object.', function () {
+            var expected = {
+                countryId: 'US',
+                regionCode: null,
+                region: null
+            };
+
+            expect(JSON.stringify(newCustomerAddress({}))).toEqual(JSON.stringify(expected));
+        });
+
+        it('Check on function call with empty address data.', function () {
+            var result = newCustomerAddress({});
+
+            expect(result.isDefaultShipping()).toBeUndefined();
+            expect(result.isDefaultBilling()).toBeUndefined();
+            expect(result.getType()).toEqual('new-customer-address');
+            expect(result.getKey()).toEqual('new-customer-address');
+            expect(result.getKey()).toContain('new-customer-address');
+            expect(result.isEditable()).toBeTruthy();
+            expect(result.canUseForBilling()).toBeTruthy();
+        });
+
+        it('Check on regionId with region object in address data.', function () {
+            var result = newCustomerAddress({
+                    region: {
+                        'region_id': 1
+                    }
+                }),
+                expected = {
+                    countryId: 'US',
+                    regionId: 1
+                };
+
+            expect(JSON.stringify(result)).toEqual(JSON.stringify(expected));
+        });
+        it('Check on regionId with countryId in address data.', function () {
+            var result = newCustomerAddress({
+                    'country_id': 'US'
+                }),
+                expected = {
+                    countryId: 'US',
+                    regionCode: null,
+                    region: null
+                };
+
+            expect(JSON.stringify(result)).toEqual(JSON.stringify(expected));
+        });
+    });
+});
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/view/cart/shipping-estimation.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/view/cart/shipping-estimation.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..785d88d81e3543aae46ad1564c7a4ba5edbcba5c
--- /dev/null
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/view/cart/shipping-estimation.test.js
@@ -0,0 +1,115 @@
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/* eslint max-nested-callbacks: 0 */
+
+define(['squire', 'ko'], function (Squire, ko) {
+    'use strict';
+
+    var injector = new Squire(),
+        checkoutProvider = {
+            on: jasmine.createSpy()
+        },
+        mocks = {
+            'Magento_Checkout/js/action/select-shipping-address': jasmine.createSpy(),
+            'Magento_Checkout/js/model/address-converter': {
+                formAddressDataToQuoteAddress: jasmine.createSpy()
+            },
+            'Magento_Checkout/js/model/cart/estimate-service': jasmine.createSpy(),
+            'Magento_Checkout/js/checkout-data': jasmine.createSpy(),
+            'Magento_Checkout/js/model/shipping-rates-validator': {
+                bindChangeHandlers: jasmine.createSpy()
+            },
+            'uiRegistry': {
+                async: jasmine.createSpy().and.returnValue(function (callback) {
+                    callback(checkoutProvider);
+                }),
+                create: jasmine.createSpy(),
+                get: jasmine.createSpy(),
+                set: jasmine.createSpy()
+            },
+            'Magento_Checkout/js/model/quote': {
+                isVirtual: jasmine.createSpy(),
+                shippingAddress: jasmine.createSpy()
+            },
+            'Magento_Checkout/js/model/checkout-data-resolver': {
+                resolveEstimationAddress: jasmine.createSpy()
+            },
+            'mage/validation': jasmine.createSpy()
+        },
+        obj;
+
+    beforeEach(function (done) {
+        injector.mock(mocks);
+        injector.require(['Magento_Checkout/js/view/cart/shipping-estimation'], function (Constr) {
+            obj = new Constr({
+                provider: 'provName',
+                name: '',
+                index: ''
+            });
+            done();
+        });
+    });
+
+    describe('Magento_Checkout/js/view/cart/shipping-estimation', function () {
+        describe('"initElement" method', function () {
+            it('Check for return value and element that initiated.', function () {
+                var element = jasmine.createSpyObj('element', ['initContainer']);
+
+                expect(obj.initElement(element)).toBe(obj);
+                expect(mocks['Magento_Checkout/js/model/shipping-rates-validator'].bindChangeHandlers)
+                    .not.toHaveBeenCalled();
+            });
+            it('Check shipping rates validator call.', function () {
+                var element = {
+                    index: 'address-fieldsets',
+                    elems: ko.observable(),
+                    initContainer: jasmine.createSpy()
+                };
+
+                spyOn(element.elems, 'subscribe');
+
+                obj.initElement(element);
+                expect(mocks['Magento_Checkout/js/model/shipping-rates-validator'].bindChangeHandlers)
+                    .toHaveBeenCalledWith(element.elems(), true, 500);
+                expect(element.elems.subscribe)
+                    .toHaveBeenCalledWith(jasmine.any(Function));
+            });
+        });
+
+        describe('"getEstimationInfo" method', function () {
+            it('Check for invalid form data.', function () {
+                obj.source = {
+                    get: jasmine.createSpy().and.returnValue(true),
+                    set: jasmine.createSpy(),
+                    trigger: jasmine.createSpy()
+                };
+
+                expect(obj.getEstimationInfo()).toBeUndefined();
+                expect(obj.source.get).toHaveBeenCalledWith('params.invalid');
+                expect(obj.source.get).not.toHaveBeenCalledWith('shippingAddress');
+                expect(obj.source.set).toHaveBeenCalledWith('params.invalid', false);
+                expect(obj.source.trigger).toHaveBeenCalledWith('shippingAddress.data.validate');
+                expect(mocks['Magento_Checkout/js/action/select-shipping-address']).not.toHaveBeenCalled();
+                obj.source = {};
+            });
+            it('Check for vaild form data.', function () {
+                obj.source = {
+                    get: jasmine.createSpy().and.returnValues(false, {}),
+                    set: jasmine.createSpy(),
+                    trigger: jasmine.createSpy()
+                };
+
+                expect(obj.getEstimationInfo()).toBeUndefined();
+                expect(obj.source.get).toHaveBeenCalledWith('params.invalid');
+                expect(obj.source.get).toHaveBeenCalledWith('shippingAddress');
+                expect(obj.source.set).toHaveBeenCalledWith('params.invalid', false);
+                expect(obj.source.trigger).toHaveBeenCalledWith('shippingAddress.data.validate');
+                expect(mocks['Magento_Checkout/js/action/select-shipping-address']).toHaveBeenCalled();
+                obj.source = {};
+            });
+        });
+    });
+});
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/view/shipping.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/view/shipping.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..20f3b2a090d7a38882a0728be94998ea7c359c70
--- /dev/null
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/view/shipping.test.js
@@ -0,0 +1,194 @@
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/* eslint max-nested-callbacks: 0 */
+require.config({
+    map: {
+        '*': {
+            'Magento_Checkout/js/view/shipping': 'Magento_Checkout/js/view/shipping'
+        }
+    }
+});
+
+define(['squire', 'ko', 'jquery', 'jquery/validate'], function (Squire, ko, $) {
+    'use strict';
+
+    var injector = new Squire(),
+        modalStub = {
+            openModal: jasmine.createSpy(),
+            closeModal: jasmine.createSpy()
+        },
+        mocks = {
+            'Magento_Customer/js/model/customer': {
+                isLoggedIn: ko.observable()
+            },
+            'Magento_Customer/js/model/address-list': ko.observableArray(),
+            'Magento_Checkout/js/model/address-converter': jasmine.createSpy(),
+            'Magento_Checkout/js/model/quote': {
+                isVirtual: jasmine.createSpy(),
+                shippingMethod: ko.observable()
+            },
+            'Magento_Checkout/js/action/create-shipping-address': jasmine.createSpy().and.returnValue(
+                jasmine.createSpyObj('newShippingAddress', ['getKey'])
+            ),
+            'Magento_Checkout/js/action/select-shipping-address': jasmine.createSpy(),
+            'Magento_Checkout/js/model/shipping-rates-validator': jasmine.createSpy(),
+            'Magento_Checkout/js/model/shipping-address/form-popup-state': {
+                isVisible: ko.observable()
+            },
+            'Magento_Checkout/js/model/shipping-service': jasmine.createSpyObj('service', ['getShippingRates']),
+            'Magento_Checkout/js/action/select-shipping-method': jasmine.createSpy(),
+            'Magento_Checkout/js/model/shipping-rate-registry': jasmine.createSpy(),
+            'Magento_Checkout/js/action/set-shipping-information': jasmine.createSpy(),
+            'Magento_Checkout/js/model/step-navigator': jasmine.createSpyObj('navigator', ['registerStep']),
+            'Magento_Ui/js/modal/modal': jasmine.createSpy('modal').and.returnValue(modalStub),
+            'Magento_Checkout/js/model/checkout-data-resolver': jasmine.createSpyObj(
+                'dataResolver',
+                ['resolveShippingAddress']
+            ),
+            'Magento_Checkout/js/checkout-data': jasmine.createSpyObj(
+                'checkoutData',
+                ['setSelectedShippingAddress', 'setNewCustomerShippingAddress', 'setSelectedShippingRate']
+            ),
+            'uiRegistry': jasmine.createSpy(),
+            'Magento_Checkout/js/model/shipping-rate-service': jasmine.createSpy()
+        },
+        obj;
+
+    beforeEach(function (done) {
+        injector.mock(mocks);
+        injector.require(['Magento_Checkout/js/view/shipping'], function (Constr) {
+            obj = new Constr({
+                provider: 'provName',
+                name: '',
+                index: '',
+                popUpForm: {
+                    options: {
+                        buttons: {
+                            save: {},
+                            cancel: {}
+                        }
+                    }
+                }
+            });
+            done();
+        });
+    });
+
+    describe('Magento_Checkout/js/view/shipping', function () {
+        describe('"navigate" method', function () {
+            it('Check for return value.', function () {
+                expect(obj.navigate()).toBeUndefined();
+            });
+        });
+
+        describe('"getPopUp" method', function () {
+            it('Check for return value.', function () {
+                expect(obj.getPopUp()).toBe(modalStub);
+                expect(mocks['Magento_Ui/js/modal/modal']).toHaveBeenCalled();
+                mocks['Magento_Ui/js/modal/modal'].calls.reset();
+            });
+            it('Check on single modal call', function () {
+                expect(obj.getPopUp()).toBe(modalStub);
+                expect(mocks['Magento_Ui/js/modal/modal']).not.toHaveBeenCalled();
+            });
+        });
+
+        describe('"showFormPopUp" method', function () {
+            it('Check method call.', function () {
+                expect(obj.showFormPopUp()).toBeUndefined();
+                expect(obj.isFormPopUpVisible()).toBeTruthy();
+                expect(modalStub.openModal).toHaveBeenCalled();
+            });
+        });
+
+        describe('"saveNewAddress" method', function () {
+            it('Check method call with invalid form data.', function () {
+                obj.source = {
+                    get: jasmine.createSpy().and.returnValue(true),
+                    set: jasmine.createSpy(),
+                    trigger: jasmine.createSpy()
+                };
+
+                expect(obj.saveNewAddress()).toBeUndefined();
+                expect(obj.isNewAddressAdded()).toBeFalsy();
+                expect(modalStub.closeModal).not.toHaveBeenCalled();
+            });
+            it('Check method call with valid form data.', function () {
+                obj.source = {
+                    get: jasmine.createSpy().and.returnValues(true, false, {}),
+                    set: jasmine.createSpy(),
+                    trigger: jasmine.createSpy()
+                };
+
+                expect(obj.saveNewAddress()).toBeUndefined();
+                expect(obj.isNewAddressAdded()).toBeTruthy();
+                expect(modalStub.closeModal).toHaveBeenCalled();
+            });
+        });
+
+        describe('"selectShippingMethod" method', function () {
+            it('Check method call.', function () {
+                var shippingMethod = {
+                    'carrier_code': 'carrier',
+                    'method_code': 'method'
+                };
+
+                expect(obj.selectShippingMethod(shippingMethod)).toBeTruthy();
+                expect(mocks['Magento_Checkout/js/checkout-data'].setSelectedShippingRate)
+                    .toHaveBeenCalledWith('carrier_method');
+            });
+        });
+
+        describe('"setShippingInformation" method', function () {
+            it('Check method call.', function () {
+                expect(obj.setShippingInformation()).toBeUndefined();
+            });
+        });
+
+        describe('"validateShippingInformation" method', function () {
+            it('Check method call on negative cases.', function () {
+                obj.source = {
+                    get: jasmine.createSpy().and.returnValue(true),
+                    set: jasmine.createSpy(),
+                    trigger: jasmine.createSpy()
+                };
+
+                expect(obj.validateShippingInformation()).toBeFalsy();
+                expect(obj.errorValidationMessage()).toBe('Please specify a shipping method.');
+                spyOn(mocks['Magento_Checkout/js/model/quote'], 'shippingMethod').and.returnValue(true);
+                spyOn(mocks['Magento_Customer/js/model/customer'], 'isLoggedIn').and.returnValue(true);
+                expect(obj.validateShippingInformation()).toBeFalsy();
+            });
+            it('Check method call on positive case.', function () {
+                $('body').append('<form data-role="email-with-possible-login">' +
+                    '<input type="text" name="username" />' +
+                    '</form>');
+                obj.source = {
+                    get: jasmine.createSpy().and.returnValue(true),
+                    set: jasmine.createSpy(),
+                    trigger: jasmine.createSpy()
+                };
+                obj.isFormInline = false;
+
+                spyOn(mocks['Magento_Checkout/js/model/quote'], 'shippingMethod').and.returnValue(true);
+                spyOn(mocks['Magento_Customer/js/model/customer'], 'isLoggedIn').and.returnValue(false);
+                spyOn($.fn, 'valid').and.returnValue(true);
+                expect(obj.validateShippingInformation()).toBeTruthy();
+            });
+        });
+
+        describe('"triggerShippingDataValidateEvent" method', function () {
+            it('Check method call.', function () {
+                obj.source = {
+                    get: jasmine.createSpy().and.returnValue(true),
+                    set: jasmine.createSpy(),
+                    trigger: jasmine.createSpy()
+                };
+                expect(obj.triggerShippingDataValidateEvent()).toBeUndefined();
+            });
+        });
+    });
+});
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Customer/frontend/js/model/customer/address.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Customer/frontend/js/model/customer/address.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..0384c9df2c583c31ad3f95a6b942b8c73b0b3af5
--- /dev/null
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Customer/frontend/js/model/customer/address.test.js
@@ -0,0 +1,58 @@
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+define([
+    'Magento_Customer/js/model/customer/address'
+], function (CustomerAddress) {
+    'use strict';
+
+    describe('Magento_Customer/js/model/customer/address', function () {
+        var customerAddress;
+
+        beforeEach(function () {
+            customerAddress = CustomerAddress;
+        });
+
+        it('Check that is executable.', function () {
+            expect(typeof customerAddress).toEqual('function');
+        });
+
+        it('Check on empty object.', function () {
+            var addressData = {
+                region: {}
+            };
+
+            expect(JSON.stringify(customerAddress(addressData))).toEqual(JSON.stringify({}));
+        });
+
+        it('Check on function call with empty address data.', function () {
+            var result = customerAddress({
+                region: {}
+            });
+
+            expect(result.isDefaultShipping()).toBeUndefined();
+            expect(result.isDefaultBilling()).toBeUndefined();
+            expect(result.getAddressInline()).toBeUndefined();
+            expect(result.getType()).toEqual('customer-address');
+            expect(result.getKey()).toContain('customer-address');
+            expect(result.getCacheKey()).toContain('customer-address');
+            expect(result.isEditable()).toBeFalsy();
+            expect(result.canUseForBilling()).toBeTruthy();
+        });
+
+        it('Check on regionId with region object in address data.', function () {
+            var result = customerAddress({
+                    region: {
+                        'region_id': 1
+                    }
+                }),
+                expected = {
+                    regionId: '1'
+                };
+
+            expect(JSON.stringify(result)).toEqual(JSON.stringify(expected));
+        });
+    });
+});
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Customer/frontend/js/view/authentication-popup.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Customer/frontend/js/view/authentication-popup.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..128bd86edbf990cc28002152ac128b134c0488be
--- /dev/null
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Customer/frontend/js/view/authentication-popup.test.js
@@ -0,0 +1,81 @@
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/* eslint max-nested-callbacks: 0 */
+define(['squire'], function (Squire) {
+    'use strict';
+
+    var injector = new Squire(),
+        loginAction = jasmine.createSpy(),
+        mocks = {
+            'Magento_Customer/js/action/login': loginAction,
+            'Magento_Customer/js/customer-data': {
+                get: jasmine.createSpy()
+            },
+            'Magento_Customer/js/model/authentication-popup': {
+                createPopUp: jasmine.createSpy(),
+                modalWindow: null
+            },
+            'Magento_Ui/js/modal/alert': jasmine.createSpy(),
+            'mage/url': jasmine.createSpyObj('customerData', ['setBaseUrl'])
+        },
+        obj;
+
+    loginAction.registerLoginCallback = jasmine.createSpy();
+    window.authenticationPopup = {
+        customerRegisterUrl: 'register_url',
+        customerForgotPasswordUrl: 'forgot_password_url',
+        autocomplete: 'autocomplete_flag',
+        baseUrl: 'base_url'
+    };
+
+    beforeEach(function (done) {
+        injector.mock(mocks);
+        injector.require(['Magento_Customer/js/view/authentication-popup'], function (Constr) {
+            obj = new Constr({
+                provider: 'provName',
+                name: '',
+                index: ''
+            });
+            done();
+        });
+    });
+
+    describe('Magento_Customer/js/view/authentication-popup', function () {
+        describe('"isActive" method', function () {
+            it('Check for return value.', function () {
+                mocks['Magento_Customer/js/customer-data'].get.and.returnValue(function () {
+                    return true;
+                });
+                expect(obj.isActive()).toBeFalsy();
+            });
+        });
+    });
+
+    describe('Magento_Customer/js/view/authentication-popup', function () {
+        describe('"setModalElement" method', function () {
+            it('Check for return value.', function () {
+                expect(obj.setModalElement()).toBeUndefined();
+                expect(mocks['Magento_Customer/js/model/authentication-popup'].createPopUp).toHaveBeenCalled();
+            });
+        });
+    });
+
+    describe('Magento_Customer/js/view/authentication-popup', function () {
+        describe('"login" method', function () {
+            it('Check for return value.', function () {
+                var event = {
+                    currentTarget: '<form><input type="text" name="username" value="customer"/></form>',
+                    stopPropagation: jasmine.createSpy()
+                };
+
+                expect(obj.login(null, event)).toBeFalsy();
+                expect(mocks['Magento_Customer/js/action/login']).toHaveBeenCalledWith({
+                    username: 'customer'
+                });
+            });
+        });
+    });
+});
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date-time.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date-time.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..4271ecc563b9ad0cda58076489a1c0a4c2f0ccf2
--- /dev/null
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date-time.test.js
@@ -0,0 +1,41 @@
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/*eslint max-nested-callbacks: 0*/
+
+define([
+    'Magento_Ui/js/form/element/date',
+    'mageUtils',
+    'moment'
+], function (DateElement, utils, moment) {
+    'use strict';
+
+    describe('Magento_Ui/js/form/element/date', function () {
+        var params, model;
+
+        beforeEach(function () {
+            params = {
+                dataScope: 'abstract',
+                options: {
+                    showsTime: true
+                }
+            };
+            model = new DateElement(params);
+        });
+
+        it('Check prepareDateTimeFormats function', function () {
+            spyOn(utils, 'convertToMomentFormat').and.callThrough();
+            model.prepareDateTimeFormats();
+            expect(utils.convertToMomentFormat).toHaveBeenCalled();
+        });
+
+        it('Check onShiftedValueChange function', function () {
+            spyOn(moment, 'tz').and.callThrough();
+            model.onShiftedValueChange('2016-12-23 9:11 PM');
+            expect(moment.tz).toHaveBeenCalled();
+        });
+
+    });
+});
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 a240e5cfd432597d4bb38e10957b4495d4ed48b2..d6480261c3fe14fe3dca807bec1375d3947972fe 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
@@ -29,13 +29,10 @@ define([
 
             it('normal + boundary values', function () {
                 expect(paging.normalize(1)).toBe(1);
-                expect(paging.normalize(2)).toBe(2);
-                expect(paging.normalize(4)).toBe(4);
             });
 
             it('out of boundary values', function () {
                 expect(paging.normalize(0)).toBe(1);
-                expect(paging.normalize(5)).toBe(4);
             });
         });
 
diff --git a/dev/tests/js/jasmine/tests/lib/mage/misc.test.js b/dev/tests/js/jasmine/tests/lib/mage/misc.test.js
index a9ea5ed90192fa46e3e223802d872be0a32afba2..62950372d3a73f54a68f7b56d0eb67c1f982402f 100644
--- a/dev/tests/js/jasmine/tests/lib/mage/misc.test.js
+++ b/dev/tests/js/jasmine/tests/lib/mage/misc.test.js
@@ -15,7 +15,7 @@ define([
             var format, momentFormat;
 
             format = 'M/d/yy';
-            momentFormat = 'MM/DD/YYYY';
+            momentFormat = 'M/DD/YYYY';
             expect(utils.convertToMomentFormat(format)).toBe(momentFormat);
         });
 
diff --git a/lib/internal/Magento/Framework/Indexer/Action/Base.php b/lib/internal/Magento/Framework/Indexer/Action/Base.php
index e7edcae5d4391e27e06020eb60467b093fec05f3..d761f388456b65114ffe0e85698a1e441e82467e 100644
--- a/lib/internal/Magento/Framework/Indexer/Action/Base.php
+++ b/lib/internal/Magento/Framework/Indexer/Action/Base.php
@@ -37,11 +37,13 @@ class Base implements ActionInterface
 
     /**
      * @var AdapterInterface
+     * @deprecated
      */
     protected $connection;
 
     /**
      * @var SourceProviderInterface[]
+     * @deprecated
      */
     protected $sources;
 
@@ -52,6 +54,7 @@ class Base implements ActionInterface
 
     /**
      * @var HandlerInterface[]
+     * @deprecated
      */
     protected $handlers;
 
@@ -62,6 +65,7 @@ class Base implements ActionInterface
 
     /**
      * @var array
+     * @deprecated
      */
     protected $columnTypesMap = [
         'varchar'    => ['type' => Table::TYPE_TEXT, 'size' => 255],
@@ -71,11 +75,13 @@ class Base implements ActionInterface
 
     /**
      * @var array
+     * @deprecated
      */
     protected $filterColumns;
 
     /**
      * @var array
+     * @deprecated
      */
     protected $searchColumns;
 
@@ -96,6 +102,7 @@ class Base implements ActionInterface
 
     /**
      * @var String
+     * @deprecated
      */
     protected $string;
 
@@ -106,11 +113,13 @@ class Base implements ActionInterface
 
     /**
      * @var array
+     * @deprecated
      */
     protected $filterable = [];
 
     /**
      * @var array
+     * @deprecated
      */
     protected $searchable = [];
 
@@ -272,6 +281,7 @@ class Base implements ActionInterface
     protected function createResultCollection()
     {
         $select = $this->getPrimaryResource()->getSelect();
+        $select->reset(\Magento\Framework\DB\Select::COLUMNS);
         $select->columns($this->getPrimaryResource()->getIdFieldName());
         foreach ($this->data['fieldsets'] as $fieldset) {
             if (isset($fieldset['references'])) {
@@ -342,6 +352,8 @@ class Base implements ActionInterface
      *
      * @param array $field
      * @return void
+     *
+     * @deprecated
      */
     protected function saveFieldByType($field)
     {
diff --git a/lib/internal/Magento/Framework/Indexer/Action/Entity.php b/lib/internal/Magento/Framework/Indexer/Action/Entity.php
index e88d281fd4b819f2ff80e7bca44cd0593b300154..b8390b9d5a0022f26f7b87da980565ea4b092829 100644
--- a/lib/internal/Magento/Framework/Indexer/Action/Entity.php
+++ b/lib/internal/Magento/Framework/Indexer/Action/Entity.php
@@ -24,6 +24,6 @@ class Entity extends Base
     {
         return !count($ids)
             ? $this->createResultCollection()
-            : $this->createResultCollection()->addFieldToFilter($this->getPrimaryResource()->getRowIdFieldName(), $ids);
+            : $this->createResultCollection()->addFieldToFilter($this->getPrimaryResource()->getIdFieldName(), $ids);
     }
 }
diff --git a/lib/internal/Magento/Framework/Indexer/SaveHandler/Batch.php b/lib/internal/Magento/Framework/Indexer/SaveHandler/Batch.php
index 31883fa8516ea112312eb897f3d0f8c0a93cfced..7d53e558287bd424afe723acf5320fb7f9a07185 100644
--- a/lib/internal/Magento/Framework/Indexer/SaveHandler/Batch.php
+++ b/lib/internal/Magento/Framework/Indexer/SaveHandler/Batch.php
@@ -10,27 +10,23 @@ class Batch
     /**
      * @param \Traversable $documents
      * @param int $size
-     * @return array
+     * @return \Generator
      */
     public function getItems(\Traversable $documents, $size)
     {
-        if (count($documents) == 0) {
-            return [];
-        }
-
         $i = 0;
-        $batch = $items = [];
+        $batch = [];
+
         foreach ($documents as $documentName => $documentValue) {
             $batch[$documentName] = $documentValue;
-            if (++$i >= $size) {
-                $items[] = $batch;
+            if (++$i == $size) {
+                yield $batch;
                 $i = 0;
                 $batch = [];
             }
         }
         if (count($batch) > 0) {
-            $items[] = $batch;
+            yield $batch;
         }
-        return $items;
     }
 }
diff --git a/lib/internal/Magento/Framework/Indexer/ScopeResolver/IndexScopeResolver.php b/lib/internal/Magento/Framework/Indexer/ScopeResolver/IndexScopeResolver.php
index eaab236bbca5bd3dddf6386f7490417bc8be584a..8bcb4acaa11a314e3bd937468cd202fd17ec81b2 100644
--- a/lib/internal/Magento/Framework/Indexer/ScopeResolver/IndexScopeResolver.php
+++ b/lib/internal/Magento/Framework/Indexer/ScopeResolver/IndexScopeResolver.php
@@ -52,6 +52,7 @@ class IndexScopeResolver implements IndexScopeResolverInterface
                     $tableNameParts[] = $dimension->getName() . $dimension->getValue();
             }
         }
+
         return $this->resource->getTableName(implode('_', $tableNameParts));
     }
 
@@ -63,10 +64,12 @@ class IndexScopeResolver implements IndexScopeResolverInterface
      */
     private function getScopeId($dimension)
     {
-        if (is_numeric($dimension->getValue())) {
-            return $dimension->getValue();
-        } else {
-            return $this->scopeResolver->getScope($dimension->getValue())->getId();
+        $scopeId = $dimension->getValue();
+
+        if (!is_numeric($scopeId)) {
+            $scopeId = $this->scopeResolver->getScope($scopeId)->getId();
         }
+
+        return $scopeId;
     }
 }
diff --git a/lib/internal/Magento/Framework/Indexer/Test/Unit/BatchTest.php b/lib/internal/Magento/Framework/Indexer/Test/Unit/BatchTest.php
index 0df98125f9a08b7dd9a63e43fdf1070a5af693de..1571bba0a7d23ce224a7d403aa63f624f58bc313 100644
--- a/lib/internal/Magento/Framework/Indexer/Test/Unit/BatchTest.php
+++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/BatchTest.php
@@ -27,7 +27,8 @@ class BatchTest extends \PHPUnit_Framework_TestCase
     public function testGetItems(array $itemsData, $size, array $expected)
     {
         $items = new \ArrayObject($itemsData);
-        $this->assertSame($expected, $this->object->getItems($items, $size));
+        $data = $this->object->getItems($items, $size);
+        $this->assertSame($expected, iterator_to_array($data));
     }
 
     /**
diff --git a/lib/web/mage/utils/misc.js b/lib/web/mage/utils/misc.js
index 29fed485f290c86f92099fc6cba68734711980d2..3fdcf3e7de542cb69ab406adcd294ed712c9cd64 100644
--- a/lib/web/mage/utils/misc.js
+++ b/lib/web/mage/utils/misc.js
@@ -220,7 +220,6 @@ define([
 
             newFormat = format.replace(/yy|y/gi, 'YYYY'); // replace the year
             newFormat = newFormat.replace(/dd|d/g, 'DD'); // replace the date
-            newFormat = newFormat.replace(/mm|m/gi, 'MM'); //replace the month
 
             return newFormat;
         }
diff --git a/package.json.sample b/package.json.sample
index 40169b3179052d98ad2c1a79baf48e376689f3c1..d73606809abe6563a57c562a27544def4ddce84a 100644
--- a/package.json.sample
+++ b/package.json.sample
@@ -36,7 +36,8 @@
         "serve-static": "^1.7.1",
         "strip-json-comments": "^1.0.2",
         "time-grunt": "^1.0.0",
-        "underscore": "^1.7.0"
+        "underscore": "^1.7.0",
+        "squirejs": "0.2.1"
     },
     "engines": {
         "node": ">=0.10.0"