diff --git a/.gitignore b/.gitignore
index 9269cefc51fa0178e49324a776bef8b575d7ac08..a5b85031db205be7a5ccdf34fbfb4ead11787617 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,6 +23,8 @@ atlassian*
 /lib/internal/flex/varien/.settings
 /node_modules
 /.grunt
+/Gruntfile.js
+/package.json
 
 /pub/media/*.*
 !/pub/media/.htaccess
diff --git a/app/code/Magento/Braintree/Model/Ui/Adminhtml/PayPal/TokenUiComponentProvider.php b/app/code/Magento/Braintree/Model/Ui/Adminhtml/PayPal/TokenUiComponentProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..fd94e18e2cd94b4e4abca81c28d5dcf90c56ff92
--- /dev/null
+++ b/app/code/Magento/Braintree/Model/Ui/Adminhtml/PayPal/TokenUiComponentProvider.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Braintree\Model\Ui\Adminhtml\PayPal;
+
+use Magento\Braintree\Gateway\Config\PayPal\Config;
+use Magento\Braintree\Model\Ui\ConfigProvider;
+use Magento\Braintree\Model\Ui\PayPal\ConfigProvider as PayPalConfigProvider;
+use Magento\Framework\UrlInterface;
+use Magento\Framework\View\Element\Template;
+use Magento\Vault\Api\Data\PaymentTokenInterface;
+use Magento\Vault\Model\Ui\TokenUiComponentInterfaceFactory;
+use Magento\Vault\Model\Ui\TokenUiComponentProviderInterface;
+
+/**
+ * Gets Ui component configuration for Braintree PayPal Vault
+ */
+class TokenUiComponentProvider implements TokenUiComponentProviderInterface
+{
+
+    /**
+     * @var TokenUiComponentInterfaceFactory
+     */
+    private $componentFactory;
+
+    /**
+     * @var UrlInterface
+     */
+    private $urlBuilder;
+
+    /**
+     * @var Config
+     */
+    private $config;
+
+    /**
+     * @param TokenUiComponentInterfaceFactory $componentFactory
+     * @param UrlInterface $urlBuilder
+     * @param Config $config
+     */
+    public function __construct(
+        TokenUiComponentInterfaceFactory $componentFactory,
+        UrlInterface $urlBuilder,
+        Config $config
+    ) {
+        $this->componentFactory = $componentFactory;
+        $this->urlBuilder = $urlBuilder;
+        $this->config = $config;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getComponentForToken(PaymentTokenInterface $paymentToken)
+    {
+        $data = json_decode($paymentToken->getTokenDetails() ?: '{}', true);
+        $data['icon'] = $this->config->getPayPalIcon();
+        $component = $this->componentFactory->create(
+            [
+                'config' => [
+                    'code' => PayPalConfigProvider::PAYPAL_VAULT_CODE,
+                    'nonceUrl' => $this->getNonceRetrieveUrl(),
+                    TokenUiComponentProviderInterface::COMPONENT_DETAILS => $data,
+                    TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH => $paymentToken->getPublicHash(),
+                    'template' => 'Magento_Braintree::form/paypal/vault.phtml'
+                ],
+                'name' => Template::class
+            ]
+        );
+
+        return $component;
+    }
+
+    /**
+     * Get url to retrieve payment method nonce
+     * @return string
+     */
+    private function getNonceRetrieveUrl()
+    {
+        return $this->urlBuilder->getUrl(ConfigProvider::CODE . '/payment/getnonce', ['_secure' => true]);
+    }
+}
diff --git a/app/code/Magento/Braintree/Model/Ui/Adminhtml/TokenUiComponentProvider.php b/app/code/Magento/Braintree/Model/Ui/Adminhtml/TokenUiComponentProvider.php
index 6cfc96ea23d0d158646c4e30be4f63aeb8ca2cd0..420b8365b3ea4f64de1ad6008238c4a706aaa4b6 100644
--- a/app/code/Magento/Braintree/Model/Ui/Adminhtml/TokenUiComponentProvider.php
+++ b/app/code/Magento/Braintree/Model/Ui/Adminhtml/TokenUiComponentProvider.php
@@ -49,6 +49,7 @@ class TokenUiComponentProvider implements TokenUiComponentProviderInterface
         $component = $this->componentFactory->create(
             [
                 'config' => [
+                    'code' => ConfigProvider::CC_VAULT_CODE,
                     'nonceUrl' => $this->getNonceRetrieveUrl(),
                     TokenUiComponentProviderInterface::COMPONENT_DETAILS => $data,
                     TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH => $paymentToken->getPublicHash(),
diff --git a/app/code/Magento/Braintree/Test/Unit/Model/Ui/Adminhtml/PayPal/TokenUiComponentProviderTest.php b/app/code/Magento/Braintree/Test/Unit/Model/Ui/Adminhtml/PayPal/TokenUiComponentProviderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..bdc39cbc5b868b52484cd550c833cfa147e68407
--- /dev/null
+++ b/app/code/Magento/Braintree/Test/Unit/Model/Ui/Adminhtml/PayPal/TokenUiComponentProviderTest.php
@@ -0,0 +1,114 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Braintree\Test\Unit\Model\Ui\Adminhtml\PayPal;
+
+use Magento\Braintree\Gateway\Config\PayPal\Config;
+use Magento\Braintree\Model\Ui\Adminhtml\PayPal\TokenUiComponentProvider;
+use Magento\Framework\UrlInterface;
+use Magento\Vault\Api\Data\PaymentTokenInterface;
+use Magento\Vault\Model\Ui\TokenUiComponentInterface;
+use Magento\Vault\Model\Ui\TokenUiComponentInterfaceFactory;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
+
+/**
+ * Contains methods to test PayPal token Ui component provider
+ */
+class TokenUiComponentProviderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var TokenUiComponentInterfaceFactory|MockObject
+     */
+    private $componentFactory;
+
+    /**
+     * @var UrlInterface|MockObject
+     */
+    private $urlBuilder;
+
+    /**
+     * @var Config|MockObject
+     */
+    private $config;
+
+    /**
+     * @var TokenUiComponentProvider
+     */
+    private $tokenUiComponentProvider;
+
+    protected function setUp()
+    {
+        $this->componentFactory = $this->getMockBuilder(TokenUiComponentInterfaceFactory::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+
+        $this->urlBuilder = $this->getMock(UrlInterface::class);
+
+        $this->config = $this->getMockBuilder(Config::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['getPayPalIcon'])
+            ->getMock();
+
+        $this->tokenUiComponentProvider = new TokenUiComponentProvider(
+            $this->componentFactory,
+            $this->urlBuilder,
+            $this->config
+        );
+    }
+
+    /**
+     * @covers \Magento\Braintree\Model\Ui\Adminhtml\PayPal\TokenUiComponentProvider::getComponentForToken
+     */
+    public function testGetComponentForToken()
+    {
+        $nonceUrl = 'https://payment/adminhtml/nonce/url';
+        $payerEmail = 'john.doe@test.com';
+        $icon = [
+            'url' => 'https://payment/adminhtml/icon.png',
+            'width' => 48,
+            'height' => 32
+        ];
+
+        $expected = [
+            'code' => 'vault',
+            'nonceUrl' => $nonceUrl,
+            'details' => [
+                'payerEmail' => $payerEmail,
+                'icon' => $icon
+            ],
+            'template' => 'vault.phtml'
+        ];
+
+        $this->config->expects(static::once())
+            ->method('getPayPalIcon')
+            ->willReturn($icon);
+
+        $paymentToken = $this->getMock(PaymentTokenInterface::class);
+        $paymentToken->expects(static::once())
+            ->method('getTokenDetails')
+            ->willReturn('{"payerEmail":" ' . $payerEmail . '"}');
+        $paymentToken->expects(static::once())
+            ->method('getPublicHash')
+            ->willReturn('cmk32dl21l');
+
+        $this->urlBuilder->expects(static::once())
+            ->method('getUrl')
+            ->willReturn($nonceUrl);
+
+        $tokenComponent = $this->getMock(TokenUiComponentInterface::class);
+        $tokenComponent->expects(static::once())
+            ->method('getConfig')
+            ->willReturn($expected);
+
+        $this->componentFactory->expects(static::once())
+            ->method('create')
+            ->willReturn($tokenComponent);
+
+        $component = $this->tokenUiComponentProvider->getComponentForToken($paymentToken);
+        static::assertEquals($tokenComponent, $component);
+        static::assertEquals($expected, $component->getConfig());
+    }
+}
diff --git a/app/code/Magento/Braintree/Test/Unit/Model/Ui/Adminhtml/TokenUiComponentProviderTest.php b/app/code/Magento/Braintree/Test/Unit/Model/Ui/Adminhtml/TokenUiComponentProviderTest.php
index d1665c71804cfa0c4ce8d1a6d2db96e09afd932c..f159136cf4c460d43b9191b58b536ff646da8b9c 100644
--- a/app/code/Magento/Braintree/Test/Unit/Model/Ui/Adminhtml/TokenUiComponentProviderTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Model/Ui/Adminhtml/TokenUiComponentProviderTest.php
@@ -7,10 +7,10 @@ namespace Magento\Braintree\Test\Unit\Model\Ui\Adminhtml;
 
 use Magento\Braintree\Model\Ui\Adminhtml\TokenUiComponentProvider;
 use Magento\Framework\UrlInterface;
-use Magento\Framework\View\Element\Template;
 use Magento\Vault\Api\Data\PaymentTokenInterface;
 use Magento\Vault\Model\Ui\TokenUiComponentInterface;
 use Magento\Vault\Model\Ui\TokenUiComponentInterfaceFactory;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 /**
  * Class TokenUiComponentProviderTest
@@ -19,12 +19,12 @@ class TokenUiComponentProviderTest extends \PHPUnit_Framework_TestCase
 {
 
     /**
-     * @var TokenUiComponentInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject
+     * @var TokenUiComponentInterfaceFactory|MockObject
      */
     private $componentFactory;
 
     /**
-     * @var UrlInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var UrlInterface|MockObject
      */
     private $urlBuilder;
 
@@ -59,6 +59,7 @@ class TokenUiComponentProviderTest extends \PHPUnit_Framework_TestCase
         $expirationDate = '12/2015';
 
         $expected = [
+            'code' => 'vault',
             'nonceUrl' => $nonceUrl,
             'details' => [
                 'type' => $type,
diff --git a/app/code/Magento/Braintree/etc/adminhtml/di.xml b/app/code/Magento/Braintree/etc/adminhtml/di.xml
index f252b977f20bd8b8616c7ddd90c08dd7ad0c5435..d154aabbb01b5cdd9db9beba05481c167fbec65d 100644
--- a/app/code/Magento/Braintree/etc/adminhtml/di.xml
+++ b/app/code/Magento/Braintree/etc/adminhtml/di.xml
@@ -47,6 +47,7 @@
         <arguments>
             <argument name="tokenUiComponentProviders" xsi:type="array">
                 <item name="braintree" xsi:type="object">Magento\Braintree\Model\Ui\Adminhtml\TokenUiComponentProvider</item>
+                <item name="braintree_paypal" xsi:type="object">Magento\Braintree\Model\Ui\Adminhtml\PayPal\TokenUiComponentProvider</item>
             </argument>
         </arguments>
     </type>
diff --git a/app/code/Magento/Braintree/etc/config.xml b/app/code/Magento/Braintree/etc/config.xml
index 095a8419c8529f20beb5f9a2be4499bade1f1301..bf19324ae7a0225b82106f26f291462b9d1e0b12 100644
--- a/app/code/Magento/Braintree/etc/config.xml
+++ b/app/code/Magento/Braintree/etc/config.xml
@@ -71,7 +71,8 @@
             </braintree_cc_vault>
             <braintree_paypal_vault>
                 <model>BraintreePayPalVaultFacade</model>
-                <title>Vault Token (Braintree PayPal)</title>
+                <title>Stored Accounts (Braintree PayPal)</title>
+                <can_use_internal>1</can_use_internal>
             </braintree_paypal_vault>
         </payment>
     </default>
diff --git a/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_index.xml b/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_index.xml
index 571c5ededeb993fd0e45d91cc2d1512d531179de..5e4f36e1c1fb4d4916e620cb440829357b1071ea 100644
--- a/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_index.xml
+++ b/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_index.xml
@@ -18,6 +18,10 @@
                 <argument name="method" xsi:type="string">braintree_cc_vault</argument>
                 <argument name="template" xsi:type="string">Magento_Vault::form/vault.phtml</argument>
             </action>
+            <action method="setMethodFormTemplate">
+                <argument name="method" xsi:type="string">braintree_paypal_vault</argument>
+                <argument name="template" xsi:type="string">Magento_Vault::form/vault.phtml</argument>
+            </action>
         </referenceBlock>
         <referenceBlock name="content">
             <block name="braintree_payment_script"
diff --git a/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml b/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml
index 68e0abc0cd009d9c2a30dff4cb545aa1b85f151c..579b82c61f690ed59bf94423e4aab00348a1546e 100644
--- a/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml
+++ b/app/code/Magento/Braintree/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml
@@ -18,6 +18,10 @@
                 <argument name="method" xsi:type="string">braintree_cc_vault</argument>
                 <argument name="template" xsi:type="string">Magento_Vault::form/vault.phtml</argument>
             </action>
+            <action method="setMethodFormTemplate">
+                <argument name="method" xsi:type="string">braintree_paypal_vault</argument>
+                <argument name="template" xsi:type="string">Magento_Vault::form/vault.phtml</argument>
+            </action>
         </referenceBlock>
     </body>
 </page>
\ No newline at end of file
diff --git a/app/code/Magento/Braintree/view/adminhtml/templates/form/paypal/vault.phtml b/app/code/Magento/Braintree/view/adminhtml/templates/form/paypal/vault.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..22930bbc656660efb6f5981fd2fb8e137ac591df
--- /dev/null
+++ b/app/code/Magento/Braintree/view/adminhtml/templates/form/paypal/vault.phtml
@@ -0,0 +1,30 @@
+<?php
+use Magento\Vault\Model\Ui\TokenUiComponentProviderInterface;
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+// @codingStandardsIgnoreFile
+
+/** @var \Magento\Framework\View\Element\Template $block */
+$details = $block->getData(TokenUiComponentProviderInterface::COMPONENT_DETAILS);
+$icon = $details['icon'];
+$id = $block->escapeHtml($block->getData('id'));
+?>
+<div data-mage-init='{
+        "Magento_Braintree/js/vault": {
+            "container": "payment_<?php /* @noEscape */ echo $id; ?>",
+            "publicHash": "<?php echo $block->escapeHtml($block->getData(TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH)); ?>",
+            "code": "<?php echo $block->escapeHtml($block->getData('code')); ?>",
+            "nonceUrl": "<?php echo $block->escapeUrl($block->getData('nonceUrl')); ?>"
+        }
+    }' id="payment_<?php /* @noEscape */ echo $id;?>" class="admin__field">
+    <div class="admin__field-control control">
+        <input type="radio" id="token_switcher_<?php /* @noEscape */ echo $id; ?>" name="payment[token_switcher]"/>
+        <img src="<?php echo $block->escapeUrl($icon['url']); ?>"
+             width="<?php echo $block->escapeHtml($icon['width']); ?>"
+             height="<?php echo $block->escapeHtml($icon['height']); ?>"
+             class="payment-icon" >
+        <span><?php echo $block->escapeHtml($details['payerEmail']); ?></span>
+    </div>
+</div>
diff --git a/app/code/Magento/Braintree/view/adminhtml/templates/form/vault.phtml b/app/code/Magento/Braintree/view/adminhtml/templates/form/vault.phtml
index 38114618847259c143ec2794d13ccaf5a5ff1349..001422d4bf911a40094d2174f9bb346866175c59 100644
--- a/app/code/Magento/Braintree/view/adminhtml/templates/form/vault.phtml
+++ b/app/code/Magento/Braintree/view/adminhtml/templates/form/vault.phtml
@@ -7,7 +7,7 @@ use Magento\Vault\Model\Ui\TokenUiComponentProviderInterface;
 // @codingStandardsIgnoreFile
 
 /** @var \Magento\Framework\View\Element\Template $block */
-$details = $block->getData('details');
+$details = $block->getData(TokenUiComponentProviderInterface::COMPONENT_DETAILS);
 $icon = $block->getData('icons')[$details['type']];
 $id = $block->escapeHtml($block->getData('id'));
 ?>
@@ -15,6 +15,7 @@ $id = $block->escapeHtml($block->getData('id'));
         "Magento_Braintree/js/vault": {
             "container": "payment_<?php /* @noEscape */ echo $id; ?>",
             "publicHash": "<?php echo $block->escapeHtml($block->getData(TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH)); ?>",
+            "code": "<?php echo $block->escapeHtml($block->getData('code')); ?>",
             "nonceUrl": "<?php echo $block->escapeUrl($block->getData('nonceUrl')); ?>"
         }
     }' id="payment_<?php /* @noEscape */ echo $id;?>" class="admin__field">
diff --git a/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js b/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js
index fcff173e7fcd44f714a6ec9f4282f838b04654aa..ea832acb537e0051e34f976c050c9b8bd7d289b7 100644
--- a/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js
+++ b/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js
@@ -14,7 +14,8 @@ define([
     return Class.extend({
         defaults: {
             $selector: null,
-            selector: 'edit_form'
+            selector: 'edit_form',
+            $container: null
         },
 
         /**
@@ -25,17 +26,18 @@ define([
             var self = this;
 
             self.$selector = $('#' + self.selector);
+            self.$container =  $('#' + self.container);
             self.$selector.on(
                 'setVaultNotActive',
                 function () {
-                    self.$selector.off('submitOrder.braintree_vault');
+                    self.$selector.off('submitOrder.' + self.getCode());
                 }
             );
-            this._super();
+            self._super();
 
-            this.initEventHandlers();
+            self.initEventHandlers();
 
-            return this;
+            return self;
         },
 
         /**
@@ -43,14 +45,14 @@ define([
          * @returns {String}
          */
         getCode: function () {
-            return 'braintree';
+            return this.code;
         },
 
         /**
          * Init event handlers
          */
         initEventHandlers: function () {
-            $('#' + this.container).find('[name="payment[token_switcher]"]')
+            $(this.$container).find('[name="payment[token_switcher]"]')
                 .on('click', this.selectPaymentMethod.bind(this));
         },
 
@@ -66,7 +68,7 @@ define([
          * Enable form event listeners
          */
         enableEventListeners: function () {
-            this.$selector.on('submitOrder.braintree_vault', this.submitOrder.bind(this));
+            this.$selector.on('submitOrder.' + this.getCode(), this.submitOrder.bind(this));
         },
 
         /**
@@ -129,7 +131,7 @@ define([
             this.createPublicHashSelector();
 
             this.$selector.find('[name="payment[public_hash]"]').val(this.publicHash);
-            this.$selector.find('#braintree_nonce').val(nonce);
+            this.$container.find('#' + this.getNonceSelectorName()).val(nonce);
         },
 
         /**
@@ -138,16 +140,16 @@ define([
         createPublicHashSelector: function () {
             var $input;
 
-            if (this.$selector.find('#braintree_nonce').size() === 0) {
+            if (this.$container.find('#' + this.getNonceSelectorName()).size() === 0) {
                 $input = $('<input>').attr(
                     {
                         type: 'hidden',
-                        id: 'braintree_nonce',
+                        id: this.getNonceSelectorName(),
                         name: 'payment[payment_method_nonce]'
                     }
                 );
 
-                $input.appendTo(this.$selector);
+                $input.appendTo(this.$container);
                 $input.prop('disabled', false);
             }
         },
@@ -160,6 +162,14 @@ define([
             alert({
                 content: message
             });
+        },
+
+        /**
+         * Get selector name for nonce input
+         * @returns {String}
+         */
+        getNonceSelectorName: function () {
+            return 'nonce_' + this.getCode();
         }
     });
 });
diff --git a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php
index b349d7da577a4056c86e04e7293cc53a7406a4d8..30b0d6f2ac72cff0062ed5dec33dd8498c696200 100644
--- a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php
+++ b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php
@@ -78,9 +78,14 @@ class Bundle extends \Magento\Catalog\Block\Product\View\AbstractView
     }
 
     /**
+     * Returns the bundle product options
+     * Will return cached options data if the product options are already initialized
+     * In a case when $stripSelection parameter is true will reload stored bundle selections collection from DB
+     *
+     * @param bool $stripSelection
      * @return array
      */
-    public function getOptions()
+    public function getOptions($stripSelection = false)
     {
         if (!$this->options) {
             $product = $this->getProduct();
@@ -96,7 +101,7 @@ class Bundle extends \Magento\Catalog\Block\Product\View\AbstractView
 
             $this->options = $optionCollection->appendSelections(
                 $selectionCollection,
-                false,
+                $stripSelection,
                 $this->catalogProduct->getSkipSaleableCheck()
             );
         }
diff --git a/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php b/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php
index 362394ccd8bd1ddb245f17d27047fddb094f107d..f11fc30f5b28f90ec7f1a2c13a9b40b714f7cebe 100644
--- a/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php
+++ b/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php
@@ -19,32 +19,34 @@ class BundleTest extends \PHPUnit_Framework_TestCase
     /** @var  \Magento\Bundle\Model\Product\PriceFactory|\PHPUnit_Framework_MockObject_MockObject */
     private $bundleProductPriceFactory;
 
-    /**
-     * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
-     */
-    protected $_objectHelper;
+    /** @var \Magento\Framework\Json\Encoder|\PHPUnit_Framework_MockObject_MockObject */
+    private $jsonEncoder;
+
+    /** @var \Magento\Catalog\Helper\Product|\PHPUnit_Framework_MockObject_MockObject */
+    private $catalogProduct;
 
     /**
-     * @var \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle
+     * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $_bundleBlock;
+    private $eventManager;
 
     /** @var  \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject */
     private $product;
 
+    /**
+     * @var \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle
+     */
+    private $bundleBlock;
+
     protected function setUp()
     {
         $objectHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+
         $this->bundleProductPriceFactory = $this->getMockBuilder(\Magento\Bundle\Model\Product\PriceFactory::class)
             ->disableOriginalConstructor()
             ->setMethods(['create'])
             ->getMock();
-        $this->_bundleBlock = $objectHelper->getObject(
-            \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle::class,
-            [
-                'productPrice' => $this->bundleProductPriceFactory
-            ]
-        );
+
         $this->product = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
             ->disableOriginalConstructor()
             ->setMethods(
@@ -57,45 +59,78 @@ class BundleTest extends \PHPUnit_Framework_TestCase
                     'getPreconfiguredValues'
                 ]
             )->getMock();
+        $registry = $this->getMockBuilder(\Magento\Framework\Registry::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['registry'])
+            ->getMock();
+        $registry->expects($this->any())
+            ->method('registry')
+            ->willReturn($this->product);
+        $this->eventManager = $this->getMockBuilder(\Magento\Framework\Event\ManagerInterface::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->jsonEncoder = $this->getMockBuilder(\Magento\Framework\Json\Encoder::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->catalogProduct = $this->getMockBuilder(\Magento\Catalog\Helper\Product::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        /** @var $bundleBlock BundleBlock */
+        $this->bundleBlock = $objectHelper->getObject(
+            \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle::class,
+            [
+                'registry' => $registry,
+                'eventManager' => $this->eventManager,
+                'jsonEncoder' => $this->jsonEncoder,
+                'productPrice' => $this->bundleProductPriceFactory,
+                'catalogProduct' => $this->catalogProduct
+            ]
+        );
     }
 
     public function testGetOptionHtmlNoRenderer()
     {
-        $option = $this->getMock(\Magento\Bundle\Model\Option::class, ['getType', '__wakeup'], [], '', false);
-        $option->expects($this->exactly(2))->method('getType')->will($this->returnValue('checkbox'));
+        $option = $this->getMockBuilder(\Magento\Bundle\Model\Option::class)
+            ->setMethods(['getType'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $option->expects($this->any())->method('getType')->willReturn('checkbox');
+
+        $layout = $this->getMockBuilder(\Magento\Framework\View\Layout::class)
+            ->setMethods(['getChildName', 'getBlock'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $layout->expects($this->any())->method('getChildName')->willReturn(false);
+        $this->bundleBlock->setLayout($layout);
 
         $this->assertEquals(
             'There is no defined renderer for "checkbox" option type.',
-            $this->_bundleBlock->getOptionHtml($option)
+            $this->bundleBlock->getOptionHtml($option)
         );
     }
 
     public function testGetOptionHtml()
     {
-        $option = $this->getMock(\Magento\Bundle\Model\Option::class, ['getType', '__wakeup'], [], '', false);
-        $option->expects($this->exactly(1))->method('getType')->will($this->returnValue('checkbox'));
-
-        $optionBlock = $this->getMock(
-            \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle\Option\Checkbox::class,
-            ['setOption', 'toHtml'],
-            [],
-            '',
-            false
-        );
-        $optionBlock->expects($this->any())->method('setOption')->will($this->returnValue($optionBlock));
-        $optionBlock->expects($this->any())->method('toHtml')->will($this->returnValue('option html'));
-        $layout = $this->getMock(
-            \Magento\Framework\View\Layout::class,
-            ['getChildName', 'getBlock'],
-            [],
-            '',
-            false
-        );
-        $layout->expects($this->any())->method('getChildName')->will($this->returnValue('name'));
-        $layout->expects($this->any())->method('getBlock')->will($this->returnValue($optionBlock));
-        $this->_bundleBlock->setLayout($layout);
+        $option = $this->getMockBuilder(\Magento\Bundle\Model\Option::class)
+            ->setMethods(['getType'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $option->expects($this->once())->method('getType')->willReturn('checkbox');
+
+        $optionBlock = $this->getMockBuilder(
+            \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle\Option\Checkbox::class
+        )->setMethods(['setOption', 'toHtml'])->disableOriginalConstructor()->getMock();
+        $optionBlock->expects($this->any())->method('setOption')->willReturnSelf();
+        $optionBlock->expects($this->any())->method('toHtml')->willReturn('option html');
+        $layout = $this->getMockBuilder(\Magento\Framework\View\Layout::class)
+            ->setMethods(['getChildName', 'getBlock'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $layout->expects($this->any())->method('getChildName')->willReturn('name');
+        $layout->expects($this->any())->method('getBlock')->willReturn($optionBlock);
+        $this->bundleBlock->setLayout($layout);
 
-        $this->assertEquals('option html', $this->_bundleBlock->getOptionHtml($option));
+        $this->assertEquals('option html', $this->bundleBlock->getOptionHtml($option));
     }
 
     public function testGetJsonConfigFixedPriceBundleNoOption()
@@ -127,12 +162,12 @@ class BundleTest extends \PHPUnit_Framework_TestCase
         ];
         $priceInfo = $this->getPriceInfoMock($prices);
 
-        $this->_bundleBlock = $this->setupBundleBlock(
+        $this->updateBundleBlock(
             $options,
             $priceInfo,
             \Magento\Bundle\Model\Product\Price::PRICE_TYPE_FIXED
         );
-        $jsonConfig = $this->_bundleBlock->getJsonConfig();
+        $jsonConfig = $this->bundleBlock->getJsonConfig();
         $this->assertEquals(110, $jsonConfig['prices']['oldPrice']['amount']);
         $this->assertEquals(100, $jsonConfig['prices']['basePrice']['amount']);
         $this->assertEquals(100, $jsonConfig['prices']['finalPrice']['amount']);
@@ -162,14 +197,14 @@ class BundleTest extends \PHPUnit_Framework_TestCase
         $bundleProductPrice->expects($this->at(0))
             ->method('getLowestPrice')
             ->with($this->product, $baseAmount)
-            ->will($this->returnValue(999));
+            ->willReturn(999);
         $bundleProductPrice->expects($this->at(1))
             ->method('getLowestPrice')
             ->with($this->product, $basePriceValue)
-            ->will($this->returnValue(888));
+            ->willReturn(888);
         $this->bundleProductPriceFactory->expects($this->once())
             ->method('create')
-            ->will($this->returnValue($bundleProductPrice));
+            ->willReturn($bundleProductPrice);
 
         $options = [
             $this->createOption(1, 'Title `1', $selections),
@@ -207,7 +242,7 @@ class BundleTest extends \PHPUnit_Framework_TestCase
 
         $this->product->expects($this->once())
             ->method('hasPreconfiguredValues')
-            ->will($this->returnValue(true));
+            ->willReturn(true);
         $preconfiguredValues = new \Magento\Framework\DataObject(
             [
                 'bundle_option' => [
@@ -217,14 +252,14 @@ class BundleTest extends \PHPUnit_Framework_TestCase
         );
         $this->product->expects($this->once())
             ->method('getPreconfiguredValues')
-            ->will($this->returnValue($preconfiguredValues));
+            ->willReturn($preconfiguredValues);
 
-        $this->_bundleBlock = $this->setupBundleBlock(
+        $this->updateBundleBlock(
             $options,
             $priceInfo,
             \Magento\Bundle\Model\Product\Price::PRICE_TYPE_FIXED
         );
-        $jsonConfig = $this->_bundleBlock->getJsonConfig();
+        $jsonConfig = $this->bundleBlock->getJsonConfig();
         $this->assertEquals(110, $jsonConfig['prices']['oldPrice']['amount']);
         $this->assertEquals(100, $jsonConfig['prices']['basePrice']['amount']);
         $this->assertEquals(100, $jsonConfig['prices']['finalPrice']['amount']);
@@ -236,86 +271,38 @@ class BundleTest extends \PHPUnit_Framework_TestCase
      * @param string $priceType
      * @return BundleBlock
      */
-    private function setupBundleBlock($options, $priceInfo, $priceType)
+    private function updateBundleBlock($options, $priceInfo, $priceType)
     {
-        $objectHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
-
-
-        $eventManager = $this->getMockBuilder(\Magento\Framework\Event\Manager::class)
-            ->disableOriginalConstructor()
-            ->getMock();
-        $eventManager->expects($this->any())->method('dispatch')->will($this->returnValue(true));
-
+        $this->eventManager->expects($this->any())->method('dispatch')->willReturn(true);
         $optionCollection = $this->getMockBuilder(\Magento\Bundle\Model\ResourceModel\Option\Collection::class)
             ->disableOriginalConstructor()
             ->getMock();
         $optionCollection->expects($this->any())
             ->method('appendSelections')
-            ->will($this->returnValue($options));
+            ->willReturn($options);
 
         $typeInstance = $this->getMockBuilder(\Magento\Bundle\Model\Product\Type::class)
             ->disableOriginalConstructor()
             ->getMock();
         $typeInstance->expects($this->any())
             ->method('getOptionsCollection')
-            ->will($this->returnValue($optionCollection));
+            ->willReturn($optionCollection);
         $typeInstance->expects($this->any())
             ->method('getStoreFilter')
-            ->will($this->returnValue(true));
+            ->willReturn(true);
 
         $this->product->expects($this->any())
             ->method('getTypeInstance')
-            ->will($this->returnValue($typeInstance));
+            ->willReturn($typeInstance);
         $this->product->expects($this->any())
             ->method('getPriceInfo')
-            ->will($this->returnValue($priceInfo));
+            ->willReturn($priceInfo);
         $this->product->expects($this->any())
             ->method('getPriceType')
-            ->will($this->returnValue($priceType));
-
-        $registry = $this->getMockBuilder(\Magento\Framework\Registry::class)
-            ->disableOriginalConstructor()
-            ->setMethods(['registry'])
-            ->getMock();
-        $registry->expects($this->once())
-            ->method('registry')
-            ->will($this->returnValue($this->product));
-
-        $taxHelperMock = $this->getMockBuilder(\Magento\Tax\Helper\Data::class)
-            ->disableOriginalConstructor()
-            ->getMock();
-
-        $context = $this->getMockBuilder(\Magento\Catalog\Block\Product\Context::class)
-            ->disableOriginalConstructor()
-            ->getMock();
-        $context->expects($this->any())
-            ->method('getRegistry')
-            ->will($this->returnValue($registry));
-        $context->expects($this->any())
-            ->method('getTaxData')
-            ->will($this->returnValue($taxHelperMock));
-        $context->expects($this->any())
-            ->method('getEventManager')
-            ->will($this->returnValue($eventManager));
-
-        $jsonEncoderMock = $this->getMockBuilder(\Magento\Framework\Json\Encoder::class)
-            ->disableOriginalConstructor()
-            ->getMock();
-        $jsonEncoderMock->expects($this->any())
+            ->willReturn($priceType);
+        $this->jsonEncoder->expects($this->any())
             ->method('encode')
             ->will($this->returnArgument(0));
-
-        /** @var $bundleBlock BundleBlock */
-        $bundleBlock = $objectHelper->getObject(
-            \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle::class,
-            [
-                'context' => $context,
-                'jsonEncoder' => $jsonEncoderMock,
-                'productPrice' => $this->bundleProductPriceFactory
-            ]
-        );
-
-        return $bundleBlock;
     }
 
     private function getPriceInfoMock($price)
@@ -331,13 +318,13 @@ class BundleTest extends \PHPUnit_Framework_TestCase
                 $priceInfoMock->expects($this->at($counter))
                     ->method('getPrice')
                     ->with($priceType)
-                    ->will($this->returnValue($priceValue));
+                    ->willReturn($priceValue);
                 $counter++;
             }
         } else {
             $priceInfoMock->expects($this->any())
                 ->method('getPrice')
-                ->will($this->returnValue($price));
+                ->willReturn($price);
         }
         return $priceInfoMock;
     }
@@ -355,7 +342,7 @@ class BundleTest extends \PHPUnit_Framework_TestCase
         foreach ($prices as $methodName => $amount) {
             $priceMock->expects($this->any())
                 ->method($methodName)
-                ->will($this->returnValue($amount));
+                ->willReturn($amount);
         }
 
         return $priceMock;
@@ -373,8 +360,8 @@ class BundleTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->setMethods(['getValue', 'getBaseAmount', 'getOptionSelectionAmount'])
             ->getMockForAbstractClass();
-        $amountPrice->expects($this->any())->method('getValue')->will($this->returnValue($value));
-        $amountPrice->expects($this->any())->method('getBaseAmount')->will($this->returnValue($baseAmount));
+        $amountPrice->expects($this->any())->method('getValue')->willReturn($value);
+        $amountPrice->expects($this->any())->method('getBaseAmount')->willReturn($baseAmount);
         foreach ($selectionAmounts as $selectionAmount) {
             $amountPrice->expects($this->any())
                 ->method('getOptionSelectionAmount')
@@ -414,7 +401,6 @@ class BundleTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->setMethods(
                 [
-                    '__wakeup',
                     'getId',
                     'getTitle',
                     'getSelections',
@@ -423,12 +409,12 @@ class BundleTest extends \PHPUnit_Framework_TestCase
                     'getIsDefault',
                 ]
             )
-            ->getMock();
-        $option->expects($this->any())->method('getId')->will($this->returnValue($id));
-        $option->expects($this->any())->method('getTitle')->will($this->returnValue($title));
-        $option->expects($this->any())->method('getSelections')->will($this->returnValue($selections));
-        $option->expects($this->any())->method('getType')->will($this->returnValue($type));
-        $option->expects($this->any())->method('getRequired')->will($this->returnValue($isRequired));
+            ->getMockForAbstractClass();
+        $option->expects($this->any())->method('getId')->willReturn($id);
+        $option->expects($this->any())->method('getTitle')->willReturn($title);
+        $option->expects($this->any())->method('getSelections')->willReturn($selections);
+        $option->expects($this->any())->method('getType')->willReturn($type);
+        $option->expects($this->any())->method('getRequired')->willReturn($isRequired);
         return $option;
     }
 
@@ -453,42 +439,72 @@ class BundleTest extends \PHPUnit_Framework_TestCase
     ) {
         $selection = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
             ->disableOriginalConstructor()
-            ->setMethods(
-                [
-                    'getSelectionId',
-                    'getSelectionQty',
-                    'getPriceInfo',
-                    'getSelectionCanChangeQty',
-                    'getName',
-                    'getIsDefault',
-                    'isSalable',
-                ]
-            )->getMock();
+            ->getMock();
         $tierPrice = $this->getMockBuilder(\Magento\Bundle\Pricing\Price\TierPrice::class)
             ->disableOriginalConstructor()
             ->setMethods(['getTierPriceList'])
             ->getMock();
-        $tierPrice->expects($this->any())
-            ->method('getTierPriceList')
-            ->will($this->returnValue($tierPriceList));
+        $tierPrice->expects($this->any())->method('getTierPriceList')->willReturn($tierPriceList);
         $priceInfo = $this->getMockBuilder(\Magento\Framework\Pricing\PriceInfo\Base::class)
             ->disableOriginalConstructor()
             ->setMethods(['getPrice'])
             ->getMock();
-        $priceInfo->expects($this->any())
-            ->method('getPrice')
-            ->will($this->returnValue($tierPrice));
-
-        $selection->expects($this->any())->method('getSelectionId')->will($this->returnValue($id));
-        $selection->expects($this->any())->method('getName')->will($this->returnValue($name));
-        $selection->expects($this->any())->method('getSelectionQty')->will($this->returnValue($qty));
-        $selection->expects($this->any())->method('getPriceInfo')->will($this->returnValue($priceInfo));
-        $selection->expects($this->any())->method('getSelectionCanChangeQty')->will(
-            $this->returnValue($isCanChangeQty)
-        );
-        $selection->expects($this->any())->method('getIsDefault')->will($this->returnValue($isDefault));
-        $selection->expects($this->any())->method('isSalable')->will($this->returnValue($isSalable));
+        $priceInfo->expects($this->any())->method('getPrice')->willReturn($tierPrice);
+        $selection->expects($this->any())->method('getSelectionId')->willReturn($id);
+        $selection->expects($this->any())->method('getName')->willReturn($name);
+        $selection->expects($this->any())->method('getSelectionQty')->willReturn($qty);
+        $selection->expects($this->any())->method('getPriceInfo')->willReturn($priceInfo);
+        $selection->expects($this->any())->method('getSelectionCanChangeQty')->willReturn($isCanChangeQty);
+        $selection->expects($this->any())->method('getIsDefault')->willReturn($isDefault);
+        $selection->expects($this->any())->method('isSalable')->willReturn($isSalable);
 
         return $selection;
     }
+
+    /**
+     * @dataProvider getOptionsDataProvider
+     * @param bool $stripSelection
+     */
+    public function testGetOptions($stripSelection)
+    {
+        $newOptions = ['option_1', 'option_2'];
+
+        $optionCollection = $this->getMockBuilder(\Magento\Bundle\Model\ResourceModel\Option\Collection::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $selectionConnection = $this->getMockBuilder(\Magento\Bundle\Model\ResourceModel\Selection\Collection::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $typeInstance = $this->getMockBuilder(\Magento\Bundle\Model\Product\Type::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $optionCollection->expects($this->any())->method('appendSelections')
+            ->with($selectionConnection, $stripSelection, true)
+            ->willReturn($newOptions);
+        $typeInstance->expects($this->any())->method('setStoreFilter')->with(0, $this->product)
+            ->willReturn($optionCollection);
+        $typeInstance->expects($this->any())->method('getStoreFilter')->willReturn(true);
+        $typeInstance->expects($this->any())->method('getOptionsCollection')->willReturn($optionCollection);
+        $typeInstance->expects($this->any())->method('getOptionsIds')->willReturn([1,2]);
+        $typeInstance->expects($this->once())->method('getSelectionsCollection')->with([1,2], $this->product)
+            ->willReturn($selectionConnection);
+        $this->product->expects($this->any())
+            ->method('getTypeInstance')->willReturn($typeInstance);
+        $this->product->expects($this->any())->method('getStoreId')  ->willReturn(0);
+        $this->catalogProduct->expects($this->once())->method('getSkipSaleableCheck')->willReturn(true);
+
+        $this->assertEquals($newOptions, $this->bundleBlock->getOptions($stripSelection));
+    }
+
+    /**
+     * @return array
+     */
+    public function getOptionsDataProvider()
+    {
+        return [
+            [true],
+            [false]
+        ];
+    }
 }
diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/bundle.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/bundle.phtml
index f0cb656843bcac4075a0df0659d97c8c349d2c00..1272e13e42526f1849e0e61695338ef107172428 100644
--- a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/bundle.phtml
+++ b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/bundle.phtml
@@ -9,7 +9,7 @@
 ?>
 
 <?php /* @var $block \Magento\Bundle\Block\Adminhtml\Catalog\Product\Composite\Fieldset\Bundle */ ?>
-<?php $options = $block->decorateArray($block->getOptions()); ?>
+<?php $options = $block->decorateArray($block->getOptions(true)); ?>
 <?php if (count($options)): ?>
 <fieldset id="catalog_product_composite_configure_fields_bundle"
           class="fieldset admin__fieldset composite-bundle<?php echo $block->getIsLastFieldset() ? ' last-fieldset' : '' ?>">
diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Helper/Form/Wysiwyg/Content.php b/app/code/Magento/Catalog/Block/Adminhtml/Helper/Form/Wysiwyg/Content.php
index d5488ecc5d085ee4a5d4b535ccf24040dbaee2a6..ac8cb91222fba47c7c686c10b45d6b81e87db2eb 100644
--- a/app/code/Magento/Catalog/Block/Adminhtml/Helper/Form/Wysiwyg/Content.php
+++ b/app/code/Magento/Catalog/Block/Adminhtml/Helper/Form/Wysiwyg/Content.php
@@ -14,6 +14,12 @@ namespace Magento\Catalog\Block\Adminhtml\Helper\Form\Wysiwyg;
 use Magento\Backend\Block\Widget\Form;
 use Magento\Backend\Block\Widget\Form\Generic;
 
+/**
+ * Class Content
+ *
+ * @deprecated
+ * @see \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav
+ */
 class Content extends Generic
 {
     /**
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Image/Upload.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Image/Upload.php
index 285f4f1e3ffade4875266c634a241768b36215e9..25bd24ef70b9492d2da5b32e2a4146e3b1a0ab07 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Image/Upload.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Image/Upload.php
@@ -50,8 +50,10 @@ class Upload extends \Magento\Backend\App\Action
      */
     public function execute()
     {
+        $imageId = $this->_request->getParam('param_name', 'image');
+
         try {
-            $result = $this->imageUploader->saveFileToTmpDir('image');
+            $result = $this->imageUploader->saveFileToTmpDir($imageId);
 
             $result['cookie'] = [
                 'name' => $this->_getSession()->getName(),
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php
index 55ae96faeb7e6424f51ec3d5a22054844ea5a812..fa29d46c615939533111d3f62c540f848f06710b 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Save.php
@@ -6,6 +6,7 @@
 namespace Magento\Catalog\Controller\Adminhtml\Category;
 
 use Magento\Store\Model\StoreManagerInterface;
+use Magento\Catalog\Api\Data\CategoryAttributeInterface;
 
 /**
  * Class Save
@@ -48,6 +49,11 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Category
      */
     private $storeManager;
 
+    /**
+     * @var \Magento\Eav\Model\Config
+     */
+    private $eavConfig;
+
     /**
      * Constructor
      *
@@ -56,31 +62,35 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Category
      * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
      * @param \Magento\Framework\View\LayoutFactory $layoutFactory
      * @param StoreManagerInterface $storeManager
+     * @param \Magento\Eav\Model\Config $eavConfig
      */
     public function __construct(
         \Magento\Backend\App\Action\Context $context,
         \Magento\Framework\Controller\Result\RawFactory $resultRawFactory,
         \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
         \Magento\Framework\View\LayoutFactory $layoutFactory,
-        StoreManagerInterface $storeManager
+        StoreManagerInterface $storeManager,
+        \Magento\Eav\Model\Config $eavConfig = null
     ) {
         parent::__construct($context);
         $this->resultRawFactory = $resultRawFactory;
         $this->resultJsonFactory = $resultJsonFactory;
         $this->layoutFactory = $layoutFactory;
         $this->storeManager = $storeManager;
+        $this->eavConfig = $eavConfig
+            ?: \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Eav\Model\Config::class);
     }
 
     /**
      * Filter category data
      *
+     * @deprecated
      * @param array $rawData
      * @return array
      */
     protected function _filterCategoryPostData(array $rawData)
     {
         $data = $rawData;
-        // @todo It is a workaround to prevent saving this data in category model and it has to be refactored in future
         if (isset($data['image']) && is_array($data['image'])) {
             if (!empty($data['image']['delete'])) {
                 $data['image'] = null;
@@ -126,7 +136,7 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Category
         $this->storeManager->setCurrentStore($store->getCode());
         $parentId = isset($categoryPostData['parent']) ? $categoryPostData['parent'] : null;
         if ($categoryPostData) {
-            $category->addData($this->_filterCategoryPostData($categoryPostData));
+            $category->addData($categoryPostData);
             if ($isNewCategory) {
                 $parentCategory = $this->getParentCategory($parentId, $storeId);
                 $category->setPath($parentCategory->getPath());
@@ -248,18 +258,30 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Category
     }
 
     /**
-     * Image data preprocessing
+     * Sets image attribute data to false if image was removed
      *
      * @param array $data
-     *
      * @return array
      */
     public function imagePreprocessing($data)
     {
-        if (empty($data['image'])) {
-            unset($data['image']);
-            $data['image']['delete'] = true;
+        $entityType = $this->eavConfig->getEntityType(CategoryAttributeInterface::ENTITY_TYPE_CODE);
+
+        foreach ($entityType->getAttributeCollection() as $attributeModel) {
+            $attributeCode = $attributeModel->getAttributeCode();
+            $backendModel = $attributeModel->getBackend();
+
+            if (isset($data[$attributeCode])) {
+                continue;
+            }
+
+            if (!$backendModel instanceof \Magento\Catalog\Model\Category\Attribute\Backend\Image) {
+                continue;
+            }
+
+            $data[$attributeCode] = false;
         }
+
         return $data;
     }
 
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php
index d59492c4065e72706f8c1a168e4a33b1c2c9e825..4eed888b3cb08b18f07e403bc172ec9615108a09 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php
@@ -131,12 +131,7 @@ class Helper
                 $productData[$field] = [];
             }
         }
-
-        foreach ($productData['website_ids'] as $websiteId => $checkboxValue) {
-            if (!$checkboxValue) {
-                unset($productData['website_ids'][$websiteId]);
-            }
-        }
+        $productData['website_ids'] = $this->filterWebsiteIds($productData['website_ids']);
 
         $wasLockedMedia = false;
         if ($product->isLockedAttribute('media')) {
@@ -422,4 +417,23 @@ class Helper
         }
         return $this->dateTimeFilter;
     }
+
+    /**
+     * Remove ids of non selected websites from $websiteIds array and return filtered data
+     * $websiteIds parameter expects array with website ids as keys and 1 (selected) or 0 (non selected) as values
+     * Only one id (default website ID) will be set to $websiteIds array when the single store mode is turned on
+     *
+     * @param array $websiteIds
+     * @return array
+     */
+    private function filterWebsiteIds($websiteIds)
+    {
+        if (!$this->storeManager->isSingleStoreMode()) {
+            $websiteIds = array_filter((array)$websiteIds);
+        } else {
+            $websiteIds[$this->storeManager->getWebsite(true)->getId()] = 1;
+        }
+
+        return $websiteIds;
+    }
 }
diff --git a/app/code/Magento/Catalog/Model/Category.php b/app/code/Magento/Catalog/Model/Category.php
index 9e855e05c7ce388dd52c11829882d5b46f634d02..906718c64c6e0bf814bda973c81168d067d887ed 100644
--- a/app/code/Magento/Catalog/Model/Category.php
+++ b/app/code/Magento/Catalog/Model/Category.php
@@ -652,14 +652,14 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements
     }
 
     /**
-     * Retrieve image URL
-     *
-     * @return string
+     * @param string $attributeCode
+     * @return bool|string
+     * @throws \Magento\Framework\Exception\LocalizedException
      */
-    public function getImageUrl()
+    public function getImageUrl($attributeCode = 'image')
     {
         $url = false;
-        $image = $this->getImage();
+        $image = $this->getData($attributeCode);
         if ($image) {
             if (is_string($image)) {
                 $url = $this->_storeManager->getStore()->getBaseUrl(
diff --git a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
index 5eb4461ace5f0e88583337a9b8c2efe2c71bad64..5e8589428fad1d17abe4480abf1d16a8b727abcb 100644
--- a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
+++ b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
@@ -21,8 +21,6 @@ class Image extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
     protected $_uploaderFactory;
 
     /**
-     * Filesystem facade
-     *
      * @var \Magento\Framework\Filesystem
      *
      * @deprecated
@@ -30,8 +28,6 @@ class Image extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
     protected $_filesystem;
 
     /**
-     * File Uploader factory
-     *
      * @var \Magento\MediaStorage\Model\File\UploaderFactory
      *
      * @deprecated
@@ -46,15 +42,16 @@ class Image extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
     protected $_logger;
 
     /**
-     * Image uploader
-     *
      * @var \Magento\Catalog\Model\ImageUploader
      */
     private $imageUploader;
 
     /**
-     * Image constructor.
-     *
+     * @var string
+     */
+    private $additionalData = '_additional_data_';
+
+    /**
      * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Filesystem $filesystem
      * @param \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory
@@ -70,8 +67,44 @@ class Image extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
     }
 
     /**
-     * Get image uploader
+     * Gets image name from $value array.
+     * Will return empty string in a case when $value is not an array
+     *
+     * @param array $value Attribute value
+     * @return string
+     */
+    private function getUploadedImageName($value)
+    {
+        if (is_array($value) && isset($value[0]['name'])) {
+            return $value[0]['name'];
+        }
+
+        return '';
+    }
+
+    /**
+     * Avoiding saving potential upload data to DB
+     * Will set empty image attribute value if image was not uploaded
      *
+     * @param \Magento\Framework\DataObject $object
+     * @return $this
+     */
+    public function beforeSave($object)
+    {
+        $attributeName = $this->getAttribute()->getName();
+        $value = $object->getData($attributeName);
+
+        if ($imageName = $this->getUploadedImageName($value)) {
+            $object->setData($this->additionalData . $attributeName, $value);
+            $object->setData($attributeName, $imageName);
+        } else if (!is_string($value)) {
+            $object->setData($attributeName, '');
+        }
+
+        return parent::beforeSave($object);
+    }
+
+    /**
      * @return \Magento\Catalog\Model\ImageUploader
      *
      * @deprecated
@@ -79,10 +112,10 @@ class Image extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
     private function getImageUploader()
     {
         if ($this->imageUploader === null) {
-            $this->imageUploader = \Magento\Framework\App\ObjectManager::getInstance()->get(
-                \Magento\Catalog\CategoryImageUpload::class
-            );
+            $this->imageUploader = \Magento\Framework\App\ObjectManager::getInstance()
+                ->get(\Magento\Catalog\CategoryImageUpload::class);
         }
+
         return $this->imageUploader;
     }
 
@@ -94,15 +127,16 @@ class Image extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
      */
     public function afterSave($object)
     {
-        $image = $object->getData($this->getAttribute()->getName(), null);
+        $value = $object->getData($this->additionalData . $this->getAttribute()->getName());
 
-        if ($image !== null) {
+        if ($imageName = $this->getUploadedImageName($value)) {
             try {
-                $this->getImageUploader()->moveFileFromTmp($image);
+                $this->getImageUploader()->moveFileFromTmp($imageName);
             } catch (\Exception $e) {
                 $this->_logger->critical($e);
             }
         }
+
         return $this;
     }
 }
diff --git a/app/code/Magento/Catalog/Model/Category/DataProvider.php b/app/code/Magento/Catalog/Model/Category/DataProvider.php
index 8626d183e2fac36e2b2fb194c418384d9ff87d82..aefd31e21ad62f8469837a801581170581555c6a 100644
--- a/app/code/Magento/Catalog/Model/Category/DataProvider.php
+++ b/app/code/Magento/Catalog/Model/Category/DataProvider.php
@@ -17,6 +17,7 @@ use Magento\Ui\Component\Form\Field;
 use Magento\Ui\DataProvider\EavValidationRules;
 use Magento\Catalog\Model\CategoryFactory;
 use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Catalog\Model\Category\Attribute\Backend\Image as ImageBackendModel;
 
 /**
  * Class DataProvider
@@ -206,11 +207,8 @@ class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
             $categoryData = $this->addUseDefaultSettings($category, $categoryData);
             $categoryData = $this->addUseConfigSettings($categoryData);
             $categoryData = $this->filterFields($categoryData);
-            if (isset($categoryData['image'])) {
-                unset($categoryData['image']);
-                $categoryData['image'][0]['name'] = $category->getData('image');
-                $categoryData['image'][0]['url'] = $category->getImageUrl();
-            }
+            $categoryData = $this->convertValues($category, $categoryData);
+
             $this->loadedData[$category->getId()] = $categoryData;
         }
         return $this->loadedData;
@@ -371,6 +369,31 @@ class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
         return array_diff_key($categoryData, array_flip($this->ignoreFields));
     }
 
+    /**
+     * Converts category image data to acceptable for rendering format
+     *
+     * @param \Magento\Catalog\Model\Category $category
+     * @param array $categoryData
+     * @return array
+     */
+    private function convertValues($category, $categoryData)
+    {
+        foreach ($category->getAttributes() as $attributeCode => $attribute) {
+            if (!isset($categoryData[$attributeCode])) {
+                continue;
+            }
+
+            if ($attribute->getBackend() instanceof ImageBackendModel) {
+                unset($categoryData[$attributeCode]);
+
+                $categoryData[$attributeCode][0]['name'] = $category->getData($attributeCode);
+                $categoryData[$attributeCode][0]['url'] = $category->getImageUrl($attributeCode);
+            }
+        }
+
+        return $categoryData;
+    }
+
     /**
      * Category's fields default values
      *
diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php
index 327729cf83695931a8c378dc91f41ab66a9e7d69..290770bd296c3bf9ef8854de86008674776ae2b7 100644
--- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php
+++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Sku.php
@@ -73,9 +73,12 @@ class Sku extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
     {
         $attribute = $this->getAttribute();
         $entity = $attribute->getEntity();
-        $increment = $this->_getLastSimilarAttributeValueIncrement($attribute, $object);
         $attributeValue = $object->getData($attribute->getAttributeCode());
+        $increment = null;
         while (!$entity->checkAttributeUniqueValue($attribute, $object)) {
+            if ($increment === null) {
+                $increment = $this->_getLastSimilarAttributeValueIncrement($attribute, $object);
+            }
             $sku = trim($attributeValue);
             if (strlen($sku . '-' . ++$increment) > self::SKU_MAX_LENGTH) {
                 $sku = substr($sku, 0, -strlen($increment) - 1);
diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php
index f17760237034041764539e533d5f1440b8dad3e4..cbf0464ca366158d4d3e4d75f65e4435f0834502 100644
--- a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php
+++ b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php
@@ -58,6 +58,11 @@ class CreateHandler implements ExtensionInterface
      */
     protected $fileStorageDb;
 
+    /**
+     * @var array
+     */
+    private $mediaAttributeCodes;
+
     /**
      * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool
      * @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository
@@ -145,9 +150,11 @@ class CreateHandler implements ExtensionInterface
         }
 
         /* @var $mediaAttribute \Magento\Catalog\Api\Data\ProductAttributeInterface */
-        foreach ($this->mediaConfig->getMediaAttributeCodes() as $mediaAttrCode) {
+        foreach ($this->getMediaAttributeCodes() as $mediaAttrCode) {
             $attrData = $product->getData($mediaAttrCode);
-
+            if (empty($attrData) && empty($clearImages) && empty($newImages) && empty($existImages)) {
+                continue;
+            }
             if (in_array($attrData, $clearImages)) {
                 $product->setData($mediaAttrCode, 'no_selection');
             }
@@ -394,4 +401,17 @@ class CreateHandler implements ExtensionInterface
             );
         }
     }
+
+    /**
+     * Get Media Attribute Codes cached value
+     *
+     * @return array
+     */
+    private function getMediaAttributeCodes()
+    {
+        if ($this->mediaAttributeCodes === null) {
+            $this->mediaAttributeCodes = $this->mediaConfig->getMediaAttributeCodes();
+        }
+        return $this->mediaAttributeCodes;
+    }
 }
diff --git a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php
index 3df4d9813a668b6fc81d7706412e1cf4e671c5e5..167dc2be15b292c4fabd9983911cd54cba89e62c 100644
--- a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php
+++ b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php
@@ -40,7 +40,6 @@ class SaveHandler
         Link $linkResource,
         ProductLinkRepositoryInterface $productLinkRepository
     ) {
-
         $this->metadataPool = $metadataPool;
         $this->linkResource = $linkResource;
         $this->productLinkRepository = $productLinkRepository;
@@ -54,12 +53,18 @@ class SaveHandler
      */
     public function execute($entityType, $entity)
     {
-        /** @var \Magento\Catalog\Api\Data\ProductInterface $entity*/
-        foreach ($this->productLinkRepository->getList($entity) as $link) {
-            $this->productLinkRepository->delete($link);
+        $link = $entity->getData($this->metadataPool->getMetadata($entityType)->getLinkField());
+        if ($this->linkResource->hasProductLinks($link)) {
+            /** @var \Magento\Catalog\Api\Data\ProductInterface $entity*/
+            foreach ($this->productLinkRepository->getList($entity) as $link) {
+                $this->productLinkRepository->delete($link);
+            }
         }
-        foreach ($entity->getProductLinks() as $link) {
-            $this->productLinkRepository->save($link);
+        $productLinks = $entity->getProductLinks();
+        if (count($productLinks) > 0) {
+            foreach ($entity->getProductLinks() as $link) {
+                $this->productLinkRepository->save($link);
+            }
         }
         return $entity;
     }
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Category.php b/app/code/Magento/Catalog/Model/ResourceModel/Category.php
index 407c2027923de4c683272773d519cf1adc7b1917..e743c5d384bdd539a15c4f666b36ce0f43f7f4d0 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Category.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Category.php
@@ -238,7 +238,9 @@ class Category extends AbstractResource
         if (!$object->getChildrenCount()) {
             $object->setChildrenCount(0);
         }
-
+        $object->setAttributeSetId(
+            $object->getAttributeSetId() ?: $this->getEntityType()->getDefaultAttributeSetId()
+        );
         if ($object->isObjectNew()) {
             if ($object->getPosition() === null) {
                 $object->setPosition($this->_getMaxPosition($object->getPath()) + 1);
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php
index 99c4316d20740edc4d3d6415bbfb06a344e7e5c7..8e93868dc7e51916a1c44997ad98045edbe1bd4f 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php
@@ -351,14 +351,11 @@ class Attribute extends \Magento\Eav\Model\Entity\Attribute implements
      */
     public function getApplyTo()
     {
-        if ($this->getData(self::APPLY_TO)) {
-            if (is_array($this->getData(self::APPLY_TO))) {
-                return $this->getData(self::APPLY_TO);
-            }
-            return explode(',', $this->getData(self::APPLY_TO));
-        } else {
-            return [];
+        $applyTo = $this->_getData(self::APPLY_TO) ?: [];
+        if (!is_array($applyTo)) {
+            $applyTo = explode(',', $applyTo);
         }
+        return $applyTo;
     }
 
     /**
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php
index b2b20b9d223e223a093d7f6ae222e19631084528..c24460981afbf8d6c6cccb79255031d8320b726f 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php
@@ -2182,12 +2182,17 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Collection\Abstrac
 
         $mediaGalleries = [];
         $linkField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField();
+        $items = $this->getItems();
+
+        $select->where('entity.' . $linkField . ' IN (?)', array_map(function ($item) {
+            return $item->getId();
+        }, $items));
 
         foreach ($this->getConnection()->fetchAll($select) as $row) {
             $mediaGalleries[$row[$linkField]][] = $row;
         }
 
-        foreach ($this->getItems() as $item) {
+        foreach ($items as $item) {
             $mediaEntries = isset($mediaGalleries[$item->getId()]) ? $mediaGalleries[$item->getId()] : [];
             $this->getGalleryReadHandler()->addMediaDataToProduct($item, $mediaEntries);
         }
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Link.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Link.php
index bbccabe5a61c969f74294398ad484e1b0d3c64f9..17bfa90e8842d4dc511d8d78f2dc23151a3934b3 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Link.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Link.php
@@ -96,6 +96,30 @@ class Link extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
         return $connection->fetchOne($select, $bind);
     }
 
+    /**
+     * Check if product has links.
+     *
+     * @param int $parentId ID of product
+     * @return bool
+     */
+    public function hasProductLinks($parentId)
+    {
+        $connection = $this->getConnection();
+        $select = $connection->select()->from(
+            $this->getMainTable(),
+            ['count' => new \Zend_Db_Expr('COUNT(*)')]
+        )->where(
+            'product_id = :product_id'
+        ) ;
+
+        return $connection->fetchOne(
+            $select,
+            [
+                'product_id' => $parentId
+            ]
+        ) > 0;
+    }
+
     /**
      * Save Product Links process
      *
diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Category/Image/UploadTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Category/Image/UploadTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..387e9a8a6a891b305170253befcd5cedb046feeb
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Category/Image/UploadTest.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Category\Image;
+
+use Magento\Catalog\Controller\Adminhtml\Category\Image\Upload as Model;
+use Magento\Framework\App\Request\Http as Request;
+use Magento\Catalog\Model\ImageUploader;
+use Magento\Framework\Controller\ResultFactory;
+use Magento\Framework\DataObject;
+
+/**
+ * Class UploadTest
+ */
+class UploadTest extends \PHPUnit_Framework_TestCase
+{
+    private $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+    }
+
+    public function executeDataProvider()
+    {
+        return [
+            ['image1', 'image1'],
+            ['image2', 'image2'],
+            [null, 'image'],
+        ];
+    }
+
+    /**
+     * @param string $name
+     * @param string $savedName
+     *
+     * @dataProvider executeDataProvider
+     */
+    public function testExecute($name, $savedName)
+    {
+        $request = $this->objectManager->getObject(Request::class);
+
+        $uploader = $this->getMock(ImageUploader::class, ['saveFileToTmpDir'], [], '', false);
+
+        $resultFactory = $this->getMock(ResultFactory::class, ['create'], [], '', false);
+
+        $resultFactory->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue(new DataObject()));
+
+        $model = $this->objectManager->getObject(Model::class, [
+            'request' => $request,
+            'resultFactory' => $resultFactory,
+            'imageUploader' => $uploader
+        ]);
+
+        $uploader->expects($this->once())
+            ->method('saveFileToTmpDir')
+            ->with($savedName)
+            ->will($this->returnValue([]));
+
+        $request->setParam('param_name', $name);
+
+        $model->execute();
+    }
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Category/SaveTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Category/SaveTest.php
index 51d99f7219575c205b61de6e5d93727633874f79..745d46710053a7c877e1bf05db47a715175b2bcb 100644
--- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Category/SaveTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Category/SaveTest.php
@@ -5,6 +5,8 @@
  */
 namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Category;
 
+use \Magento\Catalog\Controller\Adminhtml\Category\Save as Model;
+
 /**
  * Class SaveTest
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -14,67 +16,47 @@ class SaveTest extends \PHPUnit_Framework_TestCase
     /**
      * @var \Magento\Backend\Model\View\Result\RedirectFactory|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $resultRedirectFactoryMock;
-
-    /**
-     * @var \Magento\Framework\Controller\Result\RawFactory|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $resultRawFactoryMock;
+    private $resultRedirectFactoryMock;
 
     /**
      * @var \Magento\Framework\Controller\Result\JsonFactory|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $resultJsonFactoryMock;
+    private $resultJsonFactoryMock;
 
     /**
      * @var \Magento\Framework\View\LayoutFactory|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $layoutFactoryMock;
-
-    /**
-     * @var \Magento\Backend\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $contextMock;
-
-    /**
-     * @var \Magento\Framework\View\Page\Title|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $titleMock;
+    private $layoutFactoryMock;
 
     /**
      * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $requestMock;
+    private $requestMock;
 
     /**
      * @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $objectManagerMock;
+    private $objectManagerMock;
 
     /**
      * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $eventManagerMock;
-
-    /**
-     * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $responseMock;
+    private $eventManagerMock;
 
     /**
      * @var \Magento\Framework\Message\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $messageManagerMock;
+    private $messageManagerMock;
 
     /**
      * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
      */
-    protected $objectManager;
+    private $objectManager;
 
     /**
      * @var \Magento\Catalog\Controller\Adminhtml\Category\Save
      */
-    protected $save;
+    private $save;
 
     /**
      * Set up
@@ -84,24 +66,7 @@ class SaveTest extends \PHPUnit_Framework_TestCase
      */
     protected function setUp()
     {
-        $this->markTestSkipped('Due to MAGETWO-48956');
         $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
-
-        $this->contextMock = $this->getMock(
-            \Magento\Backend\App\Action\Context::class,
-            [
-                'getTitle',
-                'getRequest',
-                'getObjectManager',
-                'getEventManager',
-                'getResponse',
-                'getMessageManager',
-                'getResultRedirectFactory'
-            ],
-            [],
-            '',
-            false
-        );
         $this->resultRedirectFactoryMock = $this->getMock(
             \Magento\Backend\Model\View\Result\RedirectFactory::class,
             ['create'],
@@ -109,13 +74,6 @@ class SaveTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->resultRawFactoryMock = $this->getMock(
-            \Magento\Framework\Controller\Result\RawFactory::class,
-            [],
-            [],
-            '',
-            false
-        );
         $this->resultJsonFactoryMock = $this->getMock(
             \Magento\Framework\Controller\Result\JsonFactory::class,
             ['create'],
@@ -151,12 +109,6 @@ class SaveTest extends \PHPUnit_Framework_TestCase
             true,
             ['dispatch']
         );
-        $this->responseMock = $this->getMockForAbstractClass(
-            \Magento\Framework\App\ResponseInterface::class,
-            [],
-            '',
-            false
-        );
         $this->messageManagerMock = $this->getMockForAbstractClass(
             \Magento\Framework\Message\ManagerInterface::class,
             [],
@@ -167,23 +119,15 @@ class SaveTest extends \PHPUnit_Framework_TestCase
             ['addSuccess', 'getMessages']
         );
 
-        $this->contextMock->expects($this->any())->method('getTitle')->willReturn($this->titleMock);
-        $this->contextMock->expects($this->any())->method('getRequest')->willReturn($this->requestMock);
-        $this->contextMock->expects($this->any())->method('getObjectManager')->willReturn($this->objectManagerMock);
-        $this->contextMock->expects($this->any())->method('getEventManager')->willReturn($this->eventManagerMock);
-        $this->contextMock->expects($this->any())->method('getResponse')->willReturn($this->responseMock);
-        $this->contextMock->expects($this->any())->method('getMessageManager')->willReturn($this->messageManagerMock);
-        $this->contextMock->expects($this->any())
-            ->method('getResultRedirectFactory')
-            ->willReturn($this->resultRedirectFactoryMock);
-
         $this->save = $this->objectManager->getObject(
             \Magento\Catalog\Controller\Adminhtml\Category\Save::class,
             [
-                'context' => $this->contextMock,
-                'resultRawFactory' => $this->resultRawFactoryMock,
+                'request' => $this->requestMock,
+                'eventManager' => $this->eventManagerMock,
+                'messageManager' => $this->messageManagerMock,
                 'resultJsonFactory' => $this->resultJsonFactoryMock,
-                'layoutFactory' => $this->layoutFactoryMock
+                'layoutFactory' => $this->layoutFactoryMock,
+                'resultRedirectFactory' => $this->resultRedirectFactoryMock
             ]
         );
     }
@@ -201,6 +145,8 @@ class SaveTest extends \PHPUnit_Framework_TestCase
      */
     public function testExecute($categoryId, $storeId, $parentId)
     {
+        $this->markTestSkipped('Due to MAGETWO-48956');
+
         $rootCategoryId = \Magento\Catalog\Model\Category::TREE_ROOT_ID;
         $products = [['any_product']];
         $postData = [
@@ -577,4 +523,95 @@ class SaveTest extends \PHPUnit_Framework_TestCase
             ]
         ];
     }
+
+    /**
+     * @return array
+     */
+    public function imagePreprocessingDataProvider()
+    {
+        return [
+            [['attribute1' => null, 'attribute2' => 123]],
+            [['attribute2' => 123]]
+        ];
+    }
+
+    /**
+     * @dataProvider imagePreprocessingDataProvider
+     *
+     * @param array $data
+     */
+    public function testImagePreprocessingWithoutValue($data)
+    {
+        $eavConfig = $this->getMock(\Magento\Eav\Model\Config::class, ['getEntityType'], [], '', false);
+
+        $imageBackendModel = $this->objectManager->getObject(
+            \Magento\Catalog\Model\Category\Attribute\Backend\Image::class
+        );
+
+        $collection = new \Magento\Framework\DataObject(['attribute_collection' => [
+            new \Magento\Framework\DataObject([
+                'attribute_code' => 'attribute1',
+                'backend' => $imageBackendModel
+            ]),
+            new \Magento\Framework\DataObject([
+                'attribute_code' => 'attribute2',
+                'backend' => new \Magento\Framework\DataObject()
+            ])
+        ]]);
+
+        $eavConfig->expects($this->once())
+            ->method('getEntityType')
+            ->with(\Magento\Catalog\Api\Data\CategoryAttributeInterface::ENTITY_TYPE_CODE)
+            ->will($this->returnValue($collection));
+
+        $model = $this->objectManager->getObject(\Magento\Catalog\Controller\Adminhtml\Category\Save::class, [
+            'eavConfig' => $eavConfig
+        ]);
+
+        $result = $model->imagePreprocessing($data);
+
+        $this->assertEquals([
+            'attribute1' => false,
+            'attribute2' => 123
+        ], $result);
+    }
+
+    public function testImagePreprocessingWithValue()
+    {
+        $eavConfig = $this->getMock(\Magento\Eav\Model\Config::class, ['getEntityType'], [], '', false);
+
+        $imageBackendModel = $this->objectManager->getObject(
+            \Magento\Catalog\Model\Category\Attribute\Backend\Image::class
+        );
+
+        $collection = new \Magento\Framework\DataObject(['attribute_collection' => [
+            new \Magento\Framework\DataObject([
+                'attribute_code' => 'attribute1',
+                'backend' => $imageBackendModel
+            ]),
+            new \Magento\Framework\DataObject([
+                'attribute_code' => 'attribute2',
+                'backend' => new \Magento\Framework\DataObject()
+            ])
+        ]]);
+
+        $eavConfig->expects($this->once())
+            ->method('getEntityType')
+            ->with(\Magento\Catalog\Api\Data\CategoryAttributeInterface::ENTITY_TYPE_CODE)
+            ->will($this->returnValue($collection));
+
+        $model = $this->objectManager->getObject(Model::class, [
+            'eavConfig' => $eavConfig
+        ]);
+
+        $result = $model->imagePreprocessing([
+            'attribute1' => 'somevalue',
+            'attribute2' => null
+        ]);
+
+        $this->assertEquals([
+            'attribute1' => 'somevalue',
+            'attribute2' => null
+        ], $result);
+    }
 }
diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php
index a4218e92b3486db76afc61254553b914610d99c3..c67ed25d9c6665901beaeae6d7c2835b3bb20bc1 100644
--- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php
@@ -5,18 +5,14 @@
  */
 namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\Initialization;
 
-use Magento\Catalog\Api\Data\ProductLinkInterfaceFactory;
 use Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper;
 use Magento\Catalog\Controller\Adminhtml\Product\Initialization\StockDataFilter;
 use Magento\Catalog\Model\Product;
 use Magento\Catalog\Model\Product\Option;
-use Magento\Catalog\Model\ProductRepository;
 use Magento\Framework\App\RequestInterface;
 use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
-use Magento\Store\Api\Data\StoreInterface;
 use Magento\Store\Api\Data\WebsiteInterface;
 use Magento\Store\Model\StoreManagerInterface;
-use Magento\Framework\Stdlib\DateTime\Filter\Date as DateFilter;
 use Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory;
 use Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks;
 
@@ -34,11 +30,6 @@ class HelperTest extends \PHPUnit_Framework_TestCase
      */
     protected $objectManager;
 
-    /**
-     * @var int
-     */
-    protected $websiteId = 1;
-
     /**
      * @var Helper
      */
@@ -64,106 +55,54 @@ class HelperTest extends \PHPUnit_Framework_TestCase
      */
     protected $productMock;
 
-    /**
-     * @var StoreInterface|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $storeMock;
-
-    /**
-     * @var WebsiteInterface|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $websiteMock;
-
-    /**
-     * @var DateFilter|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $dateFilterMock;
-
-    /**
-     * @var ProductLinkInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $productLinkFactoryMock;
-
-    /**
-     * @var ProductRepository|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $productRepositoryMock;
-
     /**
      * @var ProductCustomOptionInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $customOptionFactoryMock;
 
     /**
-     * @var Option|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $customOptionMock;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Catalog\Model\Product\Link\Resolver|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $linkResolverMock;
 
     /**
-     * @var ProductLinks
+     * @var ProductLinks|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $productLinksMock;
 
     protected function setUp()
     {
         $this->objectManager = new ObjectManager($this);
-        $this->productLinkFactoryMock = $this->getMockBuilder(ProductLinkInterfaceFactory::class)
-            ->disableOriginalConstructor()
-            ->getMock();
-        $this->productRepositoryMock = $this->getMockBuilder(ProductRepository::class)
-            ->disableOriginalConstructor()
-            ->getMock();
         $this->requestMock = $this->getMockBuilder(RequestInterface::class)
             ->setMethods(['getPost'])
             ->getMockForAbstractClass();
-        $this->storeMock = $this->getMockBuilder(StoreInterface::class)
-            ->setMethods(['getWebsite'])
-            ->getMockForAbstractClass();
-        $this->websiteMock = $this->getMockBuilder(WebsiteInterface::class)
-            ->getMockForAbstractClass();
         $this->storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class)
             ->getMockForAbstractClass();
-        $this->dateFilterMock = $this->getMockBuilder(DateFilter::class)
-            ->disableOriginalConstructor()
-            ->getMock();
         $this->stockFilterMock = $this->getMockBuilder(StockDataFilter::class)
             ->disableOriginalConstructor()
             ->getMock();
         $this->productMock = $this->getMockBuilder(Product::class)
-            ->setMethods([
-                'getId',
-                'setWebsiteIds',
-                'isLockedAttribute',
-                'lockAttribute',
-                'getAttributes',
-                'unlockAttribute',
-                'getOptionsReadOnly',
-                'setCanSaveCustomOptions',
-                '__sleep',
-                '__wakeup',
-                'getSku',
-                'getProductLinks',
-                'getWebsiteIds'
-            ])
+            ->setMethods(
+                [
+                    'getId',
+                    'isLockedAttribute',
+                    'lockAttribute',
+                    'getAttributes',
+                    'unlockAttribute',
+                    'getOptionsReadOnly',
+                    'getSku',
+                    'getProductLinks',
+                ]
+            )
             ->disableOriginalConstructor()
-            ->getMock();
+            ->getMockForAbstractClass();
         $this->customOptionFactoryMock = $this->getMockBuilder(ProductCustomOptionInterfaceFactory::class)
             ->disableOriginalConstructor()
             ->setMethods(['create'])
             ->getMock();
-        $this->customOptionMock = $this->getMockBuilder(Option::class)
-            ->disableOriginalConstructor()
-            ->setMethods(null)
-            ->getMock();
         $this->productLinksMock = $this->getMockBuilder(ProductLinks::class)
             ->disableOriginalConstructor()
             ->getMock();
-
         $this->productLinksMock->expects($this->any())
             ->method('initializeLinks')
             ->willReturn($this->productMock);
@@ -173,10 +112,7 @@ class HelperTest extends \PHPUnit_Framework_TestCase
             'storeManager' => $this->storeManagerMock,
             'stockFilter' => $this->stockFilterMock,
             'productLinks' => $this->productLinksMock,
-            'dateFilter' => $this->dateFilterMock,
             'customOptionFactory' => $this->customOptionFactoryMock,
-            'productLinkFactory' => $this->productLinkFactoryMock,
-            'productRepository' => $this->productRepositoryMock,
         ]);
 
         $this->linkResolverMock = $this->getMockBuilder(\Magento\Catalog\Model\Product\Link\Resolver::class)
@@ -190,9 +126,13 @@ class HelperTest extends \PHPUnit_Framework_TestCase
 
     /**
      * @covers \Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper::initialize
-     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     * @param bool $isSingleStore
+     * @param array $websiteIds
+     * @param array $expWebsiteIds
+     *
+     * @dataProvider initializeDataProvider
      */
-    public function testInitialize()
+    public function testInitialize($isSingleStore, $websiteIds, $expWebsiteIds)
     {
         $optionsData = [
             'option1' => ['is_delete' => true, 'name' => 'name1', 'price' => 'price1', 'option_id' => ''],
@@ -202,6 +142,7 @@ class HelperTest extends \PHPUnit_Framework_TestCase
         $productData = [
             'stock_data' => ['stock_data'],
             'options' => $optionsData,
+            'website_ids' => $websiteIds
         ];
         $attributeNonDate = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class)
             ->disableOriginalConstructor()
@@ -218,69 +159,39 @@ class HelperTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->getMock();
 
-        $attributeNonDate->expects($this->any())
-            ->method('getBackend')
-            ->willReturn($attributeNonDateBackEnd);
-        $attributeDate->expects($this->any())
-            ->method('getBackend')
-            ->willReturn($attributeDateBackEnd);
-        $this->productMock->expects($this->any())
-            ->method('getProductLinks')
-            ->willReturn([]);
-        $attributeNonDateBackEnd->expects($this->any())
-            ->method('getType')
-            ->willReturn('non-datetime');
-        $attributeDateBackEnd->expects($this->any())
-            ->method('getType')
-            ->willReturn('datetime');
-
-        $attributesArray = [
-            $attributeNonDate,
-            $attributeDate
-        ];
+        $attributeNonDate->expects($this->any())->method('getBackend')->willReturn($attributeNonDateBackEnd);
+        $attributeDate->expects($this->any())->method('getBackend')->willReturn($attributeDateBackEnd);
+        $this->productMock->expects($this->any())->method('getProductLinks')->willReturn([]);
+        $attributeNonDateBackEnd->expects($this->any())->method('getType')->willReturn('non-datetime');
+        $attributeDateBackEnd->expects($this->any())->method('getType')->willReturn('datetime');
 
         $useDefaults = ['attributeCode1', 'attributeCode2'];
 
-        $this->requestMock->expects($this->at(0))
-            ->method('getPost')
-            ->with('product')
-            ->willReturn($productData);
-        $this->requestMock->expects($this->at(1))
-            ->method('getPost')
-            ->with('use_default')
-            ->willReturn($useDefaults);
+        $this->requestMock->expects($this->any())->method('getPost')->willReturnMap(
+            [
+                ['product', [], $productData],
+                ['use_default', null, $useDefaults]
+            ]
+        );
         $this->linkResolverMock->expects($this->once())->method('getLinks')->willReturn([]);
-        $this->stockFilterMock->expects($this->once())
-            ->method('filter')
-            ->with(['stock_data'])
+        $this->stockFilterMock->expects($this->once())->method('filter')->with(['stock_data'])
             ->willReturn(['stock_data']);
-        $this->productMock->expects($this->once())
-            ->method('isLockedAttribute')
-            ->with('media')
-            ->willReturn(true);
-        $this->productMock->expects($this->once())
-            ->method('unlockAttribute')
-            ->with('media');
-        $this->productMock->expects($this->any())
-            ->method('getProductLinks')
-            ->willReturn([]);
-        $this->productMock->expects($this->once())
-            ->method('lockAttribute')
-            ->with('media');
-        $this->productMock->expects($this->once())
-            ->method('getAttributes')
-            ->willReturn($attributesArray);
-
-        $this->productMock->expects($this->any())
-            ->method('getSku')
-            ->willReturn('sku');
-        $this->productMock->expects($this->any())
-            ->method('getOptionsReadOnly')
-            ->willReturn(false);
-
-        $firstExpectedCustomOption = clone $this->customOptionMock;
+        $this->productMock->expects($this->once())->method('isLockedAttribute')->with('media')->willReturn(true);
+        $this->productMock->expects($this->once())->method('unlockAttribute')->with('media');
+        $this->productMock->expects($this->any())->method('getProductLinks')->willReturn([]);
+        $this->productMock->expects($this->once())->method('lockAttribute')->with('media');
+        $this->productMock->expects($this->once())->method('getAttributes')
+            ->willReturn([$attributeNonDate, $attributeDate]);
+        $this->productMock->expects($this->any())->method('getSku')->willReturn('sku');
+        $this->productMock->expects($this->any())->method('getOptionsReadOnly')->willReturn(false);
+
+        $customOptionMock = $this->getMockBuilder(Option::class)
+            ->disableOriginalConstructor()
+            ->setMethods(null)
+            ->getMock();
+        $firstExpectedCustomOption = clone $customOptionMock;
         $firstExpectedCustomOption->setData($optionsData['option2']);
-        $secondExpectedCustomOption = clone $this->customOptionMock;
+        $secondExpectedCustomOption = clone $customOptionMock;
         $secondExpectedCustomOption->setData($optionsData['option3']);
         $this->customOptionFactoryMock->expects($this->any())
             ->method('create')
@@ -293,8 +204,13 @@ class HelperTest extends \PHPUnit_Framework_TestCase
                     $secondExpectedCustomOption
                 ]
             ]);
+        $website = $this->getMockBuilder(WebsiteInterface::class)->getMockForAbstractClass();
+        $website->expects($this->any())->method('getId')->willReturn(1);
+        $this->storeManagerMock->expects($this->once())->method('isSingleStoreMode')->willReturn($isSingleStore);
+        $this->storeManagerMock->expects($this->any())->method('getWebsite')->willReturn($website);
 
         $this->assertEquals($this->productMock, $this->helper->initialize($this->productMock));
+        $this->assertEquals($expWebsiteIds, $this->productMock->getDataByKey('website_ids'));
 
         $productOptions = $this->productMock->getOptions();
         $this->assertTrue(2 == count($productOptions));
@@ -305,6 +221,35 @@ class HelperTest extends \PHPUnit_Framework_TestCase
         $this->assertTrue('sku' == $option2->getData('product_sku'));
     }
 
+    /**
+     * @return array
+     */
+    public function initializeDataProvider()
+    {
+        return [
+            [
+                'single_store' => false,
+                'website_ids' => ['1' => 1, '2' => 1],
+                'expected_website_ids' => ['1' => 1, '2' => 1]
+            ],
+            [
+                'single_store' => false,
+                'website_ids' => ['1' => 1, '2' => 0],
+                'expected_website_ids' => ['1' => 1]
+            ],
+            [
+                'single_store' => false,
+                'website_ids' => ['1' => 0, '2' => 0],
+                'expected_website_ids' => []
+            ],
+            [
+                'single_store' => true,
+                'website_ids' => [],
+                'expected_website_ids' => ['1' => 1]
+            ],
+        ];
+    }
+
     /**
      * Data provider for testMergeProductOptions
      *
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Category/Attribute/Backend/ImageTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Category/Attribute/Backend/ImageTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..aa78fea89668773a2864741526d07c3e76aae1d1
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Category/Attribute/Backend/ImageTest.php
@@ -0,0 +1,293 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Catalog\Test\Unit\Model\Category\Attribute\Backend;
+
+class ImageTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute
+     */
+    private $attribute;
+
+    /**
+     * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * @var \Magento\Catalog\Model\ImageUploader
+     */
+    private $imageUploader;
+
+    /**
+     * @var \Psr\Log\LoggerInterface
+     */
+    private $logger;
+
+    protected function setUp()
+    {
+        $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+
+        $this->attribute = $this->getMockForAbstractClass(
+            \Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class,
+            [],
+            'TestAttribute',
+            false,
+            false,
+            true,
+            ['getName']
+        );
+
+        $this->attribute->expects($this->once())
+            ->method('getName')
+            ->will($this->returnValue('test_attribute'));
+
+        $this->logger = $this->getMockForAbstractClass(
+            \Psr\Log\LoggerInterface::class,
+            [],
+            'TestLogger',
+            false,
+            false,
+            true,
+            ['critical']
+        );
+
+        $this->imageUploader = $this->getMock(
+            \Magento\Catalog\Model\ImageUploader::class,
+            ['moveFileFromTmp'],
+            [],
+            '',
+            false
+        );
+    }
+
+    /**
+     * @return array
+     */
+    public function deletedValueDataProvider()
+    {
+        return [
+            [false],
+            [['delete' => true]]
+        ];
+    }
+
+    /**
+     * @dataProvider deletedValueDataProvider
+     *
+     * @param array $value
+     */
+    public function testBeforeSaveValueDeletion($value)
+    {
+        $model = $this->objectManager->getObject(\Magento\Catalog\Model\Category\Attribute\Backend\Image::class);
+        $model->setAttribute($this->attribute);
+
+        $object = new \Magento\Framework\DataObject([
+            'test_attribute' => $value
+        ]);
+
+        $model->beforeSave($object);
+
+        $this->assertEquals('', $object->getTestAttribute());
+    }
+
+    /**
+     * @return array
+     */
+    public function invalidValueDataProvider()
+    {
+        $closure = function () {
+            return false;
+        };
+
+        return [
+            [1234],
+            [true],
+            [new \stdClass()],
+            [$closure],
+            [['a' => 1, 'b' => 2]]
+        ];
+    }
+
+    /**
+     * @dataProvider invalidValueDataProvider
+     *
+     * @param array $value
+     */
+    public function testBeforeSaveValueInvalid($value)
+    {
+        $model = $this->objectManager->getObject(\Magento\Catalog\Model\Category\Attribute\Backend\Image::class);
+        $model->setAttribute($this->attribute);
+
+        $object = new \Magento\Framework\DataObject([
+            'test_attribute' => $value
+        ]);
+
+        $model->beforeSave($object);
+
+        $this->assertEquals('', $object->getTestAttribute());
+    }
+
+    public function testBeforeSaveAttributeFileName()
+    {
+        $model = $this->objectManager->getObject(\Magento\Catalog\Model\Category\Attribute\Backend\Image::class);
+        $model->setAttribute($this->attribute);
+
+        $object = new \Magento\Framework\DataObject([
+            'test_attribute' => [
+                ['name' => 'test123.jpg']
+            ]
+        ]);
+
+        $model->beforeSave($object);
+
+        $this->assertEquals('test123.jpg', $object->getTestAttribute());
+    }
+
+    public function testBeforeSaveTemporaryAttribute()
+    {
+        $model = $this->objectManager->getObject(\Magento\Catalog\Model\Category\Attribute\Backend\Image::class);
+        $model->setAttribute($this->attribute);
+
+        $object = new \Magento\Framework\DataObject([
+            'test_attribute' => [
+                ['name' => 'test123.jpg', 'tmp_name' => 'abc123', 'url' => 'http://www.example.com/test123.jpg']
+            ]
+        ]);
+
+        $model->beforeSave($object);
+
+        $this->assertEquals([
+            ['name' => 'test123.jpg', 'tmp_name' => 'abc123', 'url' => 'http://www.example.com/test123.jpg']
+        ], $object->getData('_additional_data_test_attribute'));
+    }
+
+    public function testBeforeSaveAttributeStringValue()
+    {
+        $model = $this->objectManager->getObject(\Magento\Catalog\Model\Category\Attribute\Backend\Image::class);
+        $model->setAttribute($this->attribute);
+
+        $object = new \Magento\Framework\DataObject([
+            'test_attribute' => 'test123.jpg'
+        ]);
+
+        $model->beforeSave($object);
+
+        $this->assertEquals('test123.jpg', $object->getTestAttribute());
+        $this->assertNull($object->getData('_additional_data_test_attribute'));
+    }
+
+    /**
+     * @return \Magento\Catalog\Model\Category\Attribute\Backend\Image
+     */
+    private function setUpModelForAfterSave()
+    {
+        $objectManagerMock = $this->getMock(
+            \Magento\Framework\App\ObjectManager::class,
+            ['get'],
+            [],
+            '',
+            false
+        );
+
+        $imageUploaderMock = $this->imageUploader;
+
+        $objectManagerMock->expects($this->any())
+            ->method('get')
+            ->will($this->returnCallback(function ($class, $params = []) use ($imageUploaderMock) {
+                if ($class == \Magento\Catalog\CategoryImageUpload::class) {
+                    return $imageUploaderMock;
+                }
+
+                return $this->objectManager->get($class, $params);
+            }));
+
+        $model = $this->objectManager->getObject(\Magento\Catalog\Model\Category\Attribute\Backend\Image::class, [
+            'objectManager' => $objectManagerMock,
+            'logger' => $this->logger
+        ]);
+        $this->objectManager->setBackwardCompatibleProperty($model, 'imageUploader', $this->imageUploader);
+
+        return $model->setAttribute($this->attribute);
+    }
+
+    public function attributeValueDataProvider()
+    {
+        return [
+            [[['name' => 'test1234.jpg']]],
+            ['test1234.jpg'],
+            [''],
+            [false]
+        ];
+    }
+
+    /**
+     * @dataProvider attributeValueDataProvider
+     *
+     * @param array $value
+     */
+    public function testAfterSaveWithAdditionalData($value)
+    {
+        $model = $this->setUpModelForAfterSave();
+
+        $this->imageUploader->expects($this->once())
+            ->method('moveFileFromTmp')
+            ->with($this->equalTo('test1234.jpg'));
+
+        $object = new \Magento\Framework\DataObject(
+            [
+                'test_attribute' => $value,
+                '_additional_data_test_attribute' => [['name' => 'test1234.jpg']]
+            ]
+        );
+
+        $model->afterSave($object);
+    }
+
+    /**
+     * @dataProvider attributeValueDataProvider
+     *
+     * @param array $value
+     */
+    public function testAfterSaveWithoutAdditionalData($value)
+    {
+        $model = $this->setUpModelForAfterSave();
+
+        $this->imageUploader->expects($this->never())
+            ->method('moveFileFromTmp');
+
+        $object = new \Magento\Framework\DataObject(
+            [
+                'test_attribute' => $value
+            ]
+        );
+
+        $model->afterSave($object);
+    }
+
+    public function testAfterSaveWithExceptions()
+    {
+        $model = $this->setUpModelForAfterSave();
+
+        $exception = new \Exception();
+
+        $this->imageUploader->expects($this->any())
+            ->method('moveFileFromTmp')
+            ->will($this->throwException($exception));
+
+        $this->logger->expects($this->once())
+            ->method('critical')
+            ->with($this->equalTo($exception));
+
+        $object = new \Magento\Framework\DataObject(
+            [
+                '_additional_data_test_attribute' => [['name' => 'test1234.jpg']]
+            ]
+        );
+
+        $model->afterSave($object);
+    }
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryTest.php
index 471037f1d3f450c1b2281e06f823222e7f7e28b6..37d0751a81bc06cfb4672874fff20dfefab6cb72 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryTest.php
@@ -9,6 +9,7 @@
 namespace Magento\Catalog\Test\Unit\Model;
 
 use Magento\Catalog\Model\Indexer;
+use Magento\Catalog\Model\Category;
 
 /**
  * @SuppressWarnings(PHPMD.TooManyFields)
@@ -16,113 +17,131 @@ use Magento\Catalog\Model\Indexer;
  */
 class CategoryTest extends \PHPUnit_Framework_TestCase
 {
-    /** @var \Magento\Catalog\Model\Category */
-    protected $category;
-
-    /** @var \Magento\Framework\Model\Context|\PHPUnit_Framework_MockObject_MockObject */
-    protected $context;
-
-    /** @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject */
-    protected $eventManager;
+    /**
+     * @var \Magento\Catalog\Model\Category
+     */
+    private $category;
 
-    /** @var \Magento\Framework\App\CacheInterface|\PHPUnit_Framework_MockObject_MockObject */
-    protected $cacheManager;
+    /**
+     * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $registry;
 
-    /** @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject */
-    protected $registry;
+    /**
+     * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $storeManager;
 
-    /** @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject */
-    protected $storeManager;
+    /**
+     * @var \Magento\Catalog\Model\ResourceModel\Category\Tree|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $categoryTreeResource;
 
-    /** @var \Magento\Catalog\Model\ResourceModel\Category\Tree|\PHPUnit_Framework_MockObject_MockObject */
-    protected $categoryTreeResource;
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $categoryTreeFactory;
 
-    /** @var \PHPUnit_Framework_MockObject_MockObject */
-    protected $categoryTreeFactory;
+    /**
+     * @var \Magento\Catalog\Api\CategoryRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $categoryRepository;
 
-    /** @var \Magento\Catalog\Api\CategoryRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */
-    protected $categoryRepository;
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $storeCollectionFactory;
 
-    /** @var \PHPUnit_Framework_MockObject_MockObject */
-    protected $storeCollectionFactory;
+    /**
+     * @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $url;
 
-    /** @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject */
-    protected $url;
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productCollectionFactory;
 
-    /** @var \PHPUnit_Framework_MockObject_MockObject */
-    protected $productCollectionFactory;
+    /**
+     * @var \Magento\Catalog\Model\Config|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $catalogConfig;
 
-    /** @var \Magento\Catalog\Model\Config|\PHPUnit_Framework_MockObject_MockObject */
-    protected $catalogConfig;
+    /**
+     * @var \Magento\Framework\Filter\FilterManager|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $filterManager;
 
-    /** @var \Magento\Framework\Filter\FilterManager|\PHPUnit_Framework_MockObject_MockObject */
-    protected $filterManager;
+    /**
+     * @var \Magento\Catalog\Model\Indexer\Category\Flat\State|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $flatState;
 
-    /** @var \Magento\Catalog\Model\Indexer\Category\Flat\State|\PHPUnit_Framework_MockObject_MockObject */
-    protected $flatState;
+    /**
+     * @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $flatIndexer;
 
-    /** @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject */
-    protected $flatIndexer;
+    /**
+     * @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productIndexer;
 
-    /** @var \Magento\Framework\Indexer\IndexerInterface|\PHPUnit_Framework_MockObject_MockObject */
-    protected $productIndexer;
+    /**
+     * @var \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $categoryUrlPathGenerator;
 
-    /** @var \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator|\PHPUnit_Framework_MockObject_MockObject */
-    protected $categoryUrlPathGenerator;
+    /**
+     * @var \Magento\UrlRewrite\Model\UrlFinderInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $urlFinder;
 
-    /** @var \Magento\UrlRewrite\Model\UrlFinderInterface|\PHPUnit_Framework_MockObject_MockObject */
-    protected $urlFinder;
+    /**
+     * @var \Magento\Framework\Model\ResourceModel\AbstractResource|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $resource;
 
-    /** @var \Magento\Framework\Model\ResourceModel\AbstractResource|\PHPUnit_Framework_MockObject_MockObject */
-    protected $resource;
+    /**
+     * @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $indexerRegistry;
 
-    /** @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject */
-    protected $indexerRegistry;
+    /**
+     * @var \Magento\Catalog\Api\CategoryAttributeRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $metadataServiceMock;
 
     /**
      * @var \PHPUnit_Framework_MockObject_MockObject
      */
-    protected $metadataServiceMock;
+    private $attributeValueFactory;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
      */
-    protected $attributeValueFactory;
+    private $objectManager;
 
     protected function setUp()
     {
-        $this->context = $this->getMock(
-            \Magento\Framework\Model\Context::class,
-            ['getEventDispatcher', 'getCacheManager'],
+        $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+        $this->registry = $this->getMock(\Magento\Framework\Registry::class);
+        $this->storeManager = $this->getMock(\Magento\Store\Model\StoreManagerInterface::class);
+        $this->categoryTreeResource = $this->getMock(
+            \Magento\Catalog\Model\ResourceModel\Category\Tree::class,
+            [],
             [],
             '',
             false
         );
-
-        $this->eventManager = $this->getMock(\Magento\Framework\Event\ManagerInterface::class);
-        $this->context->expects($this->any())->method('getEventDispatcher')
-            ->will($this->returnValue($this->eventManager));
-        $this->cacheManager = $this->getMock(\Magento\Framework\App\CacheInterface::class);
-        $this->context->expects($this->any())->method('getCacheManager')
-            ->will($this->returnValue($this->cacheManager));
-
-        $this->registry = $this->getMock(\Magento\Framework\Registry::class);
-        $this->storeManager = $this->getMock(\Magento\Store\Model\StoreManagerInterface::class);
-        $this->categoryTreeResource = $this->getMock(
-            \Magento\Catalog\Model\ResourceModel\Category\Tree::class,
-            [],
-            [],
-            '',
-            false
-        );
-        $this->categoryTreeFactory = $this->getMock(
+        $this->categoryTreeFactory = $this->getMock(
             \Magento\Catalog\Model\ResourceModel\Category\TreeFactory::class,
             ['create'],
             [],
             '',
             false);
         $this->categoryRepository = $this->getMock(\Magento\Catalog\Api\CategoryRepositoryInterface::class);
-        $this->storeCollectionFactory = $this->getMock(
+        $this->storeCollectionFactory = $this->getMock(
             \Magento\Store\Model\ResourceModel\Store\CollectionFactory::class,
             ['create'],
             [],
@@ -130,7 +149,7 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->url = $this->getMock(\Magento\Framework\UrlInterface::class);
-        $this->productCollectionFactory = $this->getMock(
+        $this->productCollectionFactory = $this->getMock(
             \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory::class,
             ['create'],
             [],
@@ -138,7 +157,7 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->catalogConfig = $this->getMock(\Magento\Catalog\Model\Config::class, [], [], '', false);
-        $this->filterManager = $this->getMock(
+        $this->filterManager = $this->getMock(
             \Magento\Framework\Filter\FilterManager::class,
             ['translitUrl'],
             [],
@@ -148,7 +167,7 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
         $this->flatState = $this->getMock(\Magento\Catalog\Model\Indexer\Category\Flat\State::class, [], [], '', false);
         $this->flatIndexer = $this->getMock(\Magento\Framework\Indexer\IndexerInterface::class);
         $this->productIndexer = $this->getMock(\Magento\Framework\Indexer\IndexerInterface::class);
-        $this->categoryUrlPathGenerator = $this->getMock(
+        $this->categoryUrlPathGenerator = $this->getMock(
             \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator::class,
             [],
             [],
@@ -156,19 +175,19 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->urlFinder = $this->getMock(\Magento\UrlRewrite\Model\UrlFinderInterface::class);
-        $this->resource = $this->getMock(
+        $this->resource = $this->getMock(
             \Magento\Catalog\Model\ResourceModel\Category::class,
             [],
             [],
             '',
             false
         );
-        $this->indexerRegistry = $this->getMock(
-            \Magento\Framework\Indexer\IndexerRegistry::class,
-            ['get'],
-            [],
-            '',
-            false
+        $this->indexerRegistry = $this->getMock(
+            \Magento\Framework\Indexer\IndexerRegistry::class,
+            ['get'],
+            [],
+            '',
+            false
         );
 
         $this->metadataServiceMock = $this->getMock(\Magento\Catalog\Api\CategoryAttributeRepositoryInterface::class);
@@ -198,7 +217,7 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
     public function testMoveWhenCannotFindParentCategory()
     {
         $this->markTestIncomplete('MAGETWO-31165');
-        $parentCategory = $this->getMock(
+        $parentCategory = $this->getMock(
             \Magento\Catalog\Model\Category::class,
             ['getId', 'setStoreId', 'load'],
             [],
@@ -223,7 +242,7 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
      */
     public function testMoveWhenCannotFindNewCategory()
     {
-        $parentCategory = $this->getMock(
+        $parentCategory = $this->getMock(
             \Magento\Catalog\Model\Category::class,
             ['getId', 'setStoreId', 'load'],
             [],
@@ -250,7 +269,7 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
     public function testMoveWhenParentCategoryIsSameAsChildCategory()
     {
         $this->markTestIncomplete('MAGETWO-31165');
-        $parentCategory = $this->getMock(
+        $parentCategory = $this->getMock(
             \Magento\Catalog\Model\Category::class,
             ['getId', 'setStoreId', 'load'],
             [],
@@ -277,7 +296,7 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
             ->method('get')
             ->with('catalog_category_product')
             ->will($this->returnValue($indexer));
-        $parentCategory = $this->getMock(
+        $parentCategory = $this->getMock(
             \Magento\Catalog\Model\Category::class,
             ['getId', 'setStoreId', 'load'],
             [],
@@ -313,10 +332,9 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
 
     protected function getCategoryModel()
     {
-        return (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject(
+        return $this->objectManager->getObject(
             \Magento\Catalog\Model\Category::class,
             [
-                'context' => $this->context,
                 'registry' => $this->registry,
                 'storeManager' => $this->storeManager,
                 'categoryTreeResource' => $this->categoryTreeResource,
@@ -487,4 +505,76 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
             $this->category->getCustomAttribute($descriptionAttributeCode)->getValue()
         );
     }
+
+    /**
+     * @return array
+     */
+    public function getImageWithAttributeCodeDataProvider()
+    {
+        return [
+            ['testimage', 'http://www.example.com/catalog/category/testimage'],
+            [false, false]
+        ];
+    }
+
+    /**
+     * @param string|bool $value
+     * @param string|bool $url
+     *
+     * @dataProvider getImageWithAttributeCodeDataProvider
+     */
+    public function testGetImageWithAttributeCode($value, $url)
+    {
+        $storeManager = $this->getMock(\Magento\Store\Model\StoreManager::class, ['getStore'], [], '', false);
+        $store = $this->getMock(\Magento\Store\Model\Store::class, ['getBaseUrl'], [], '', false);
+
+        $storeManager->expects($this->any())
+            ->method('getStore')
+            ->will($this->returnValue($store));
+
+        $store->expects($this->any())
+            ->method('getBaseUrl')
+            ->with(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA)
+            ->will($this->returnValue('http://www.example.com/'));
+
+        /** @var \Magento\Catalog\Model\Category $model */
+        $model = $this->objectManager->getObject(
+            \Magento\Catalog\Model\Category::class,
+            [
+                'storeManager' => $storeManager
+            ]
+        );
+
+        $model->setData('attribute1', $value);
+
+        $result = $model->getImageUrl('attribute1');
+
+        $this->assertEquals($url, $result);
+    }
+
+    public function testGetImageWithoutAttributeCode()
+    {
+        $storeManager = $this->getMock(\Magento\Store\Model\StoreManager::class, ['getStore'], [], '', false);
+        $store = $this->getMock(\Magento\Store\Model\Store::class, ['getBaseUrl'], [], '', false);
+
+        $storeManager->expects($this->any())
+            ->method('getStore')
+            ->will($this->returnValue($store));
+
+        $store->expects($this->any())
+            ->method('getBaseUrl')
+            ->with(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA)
+            ->will($this->returnValue('http://www.example.com/'));
+
+        /** @var \Magento\Catalog\Model\Category $model */
+        $model = $this->objectManager->getObject(\Magento\Catalog\Model\Category::class, [
+            'storeManager' => $storeManager
+        ]);
+
+        $model->setData('image', 'myimage');
+
+        $result = $model->getImageUrl();
+
+        $this->assertEquals('http://www.example.com/catalog/category/myimage', $result);
+    }
 }
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php
index 332e775b019b238b9ba1aec83f0f42302aafa68a..b97b7d2f9842355af1195b7b0ce7ed1d4aa7e4e8 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php
@@ -30,6 +30,26 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
      */
     protected $collection;
 
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $galleryResourceMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $entityMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $metadataPoolMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $galleryReadHandlerMock;
+
     /**
      * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
      */
@@ -100,24 +120,49 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->getMock();
 
-        $entityMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\AbstractEntity::class)
+        $this->entityMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\AbstractEntity::class)
             ->disableOriginalConstructor()
             ->getMock();
 
+        $this->galleryResourceMock = $this->getMockBuilder(
+            \Magento\Catalog\Model\ResourceModel\Product\Gallery::class
+        )->disableOriginalConstructor()->getMock();
+
+        $this->metadataPoolMock = $this->getMockBuilder(
+            \Magento\Framework\EntityManager\MetadataPool::class
+        )->disableOriginalConstructor()->getMock();
+
+        $this->galleryReadHandlerMock = $this->getMockBuilder(
+            \Magento\Catalog\Model\Product\Gallery\ReadHandler::class
+        )->disableOriginalConstructor()->getMock();
+
         $storeManager->expects($this->any())->method('getId')->willReturn(1);
         $storeManager->expects($this->any())->method('getStore')->willReturnSelf();
         $universalFactory->expects($this->exactly(1))->method('create')->willReturnOnConsecutiveCalls(
-            $entityMock
+            $this->entityMock
         );
-        $entityMock->expects($this->once())->method('getConnection')->willReturn($this->connectionMock);
-        $entityMock->expects($this->once())->method('getDefaultAttributes')->willReturn([]);
-        $entityMock->expects($this->any())->method('getTable')->willReturnArgument(0);
+        $this->entityMock->expects($this->once())->method('getConnection')->willReturn($this->connectionMock);
+        $this->entityMock->expects($this->once())->method('getDefaultAttributes')->willReturn([]);
+        $this->entityMock->expects($this->any())->method('getTable')->willReturnArgument(0);
         $this->connectionMock->expects($this->atLeastOnce())->method('select')->willReturn($this->selectMock);
         $helper = new ObjectManager($this);
 
         $this->prepareObjectManager([
-            [\Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class,
+            [
+                \Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class,
                 $this->getMock(\Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class)
+            ],
+            [
+                \Magento\Catalog\Model\ResourceModel\Product\Gallery::class,
+                $this->galleryResourceMock
+            ],
+            [
+                \Magento\Framework\EntityManager\MetadataPool::class,
+                $this->metadataPoolMock
+            ],
+            [
+                \Magento\Catalog\Model\Product\Gallery\ReadHandler::class,
+                $this->galleryReadHandlerMock
             ]
         ]);
         $this->collection = $helper->getObject(
@@ -150,8 +195,8 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
 
     public function testAddProductCategoriesFilter()
     {
-        $condition = ['in' => [1,2]];
-        $values = [1,2];
+        $condition = ['in' => [1, 2]];
+        $values = [1, 2];
         $conditionType = 'nin';
         $preparedSql = "category_id IN(1,2)";
         $tableName = "catalog_category_product";
@@ -174,6 +219,47 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
         $this->collection->addCategoriesFilter([$conditionType => $values]);
     }
 
+    public function testAddMediaGalleryData()
+    {
+        $attributeId = 42;
+        $itemId = 4242;
+        $linkField = 'entity_id';
+        $mediaGalleriesMock = [[$linkField => $itemId]];
+        $itemMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $attributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $metadataMock = $this->getMockBuilder(\Magento\Framework\EntityManager\EntityMetadataInterface::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->collection->addItem($itemMock);
+        $reflection = new \ReflectionClass(get_class($this->collection));
+        $reflectionProperty = $reflection->getProperty('_isCollectionLoaded');
+        $reflectionProperty->setAccessible(true);
+        $reflectionProperty->setValue($this->collection, true);
+
+        $this->galleryResourceMock->expects($this->once())->method('createBatchBaseSelect')->willReturn($selectMock);
+        $attributeMock->expects($this->once())->method('getAttributeId')->willReturn($attributeId);
+        $this->entityMock->expects($this->once())->method('getAttribute')->willReturn($attributeMock);
+        $itemMock->expects($this->atLeastOnce())->method('getId')->willReturn($itemId);
+        $selectMock->expects($this->once())->method('where')->with('entity.' . $linkField . ' IN (?)', [$itemId]);
+        $this->metadataPoolMock->expects($this->once())->method('getMetadata')->willReturn($metadataMock);
+        $metadataMock->expects($this->once())->method('getLinkField')->willReturn($linkField);
+
+        $this->connectionMock->expects($this->once())->method('fetchAll')->with($selectMock)->willReturn(
+            [['entity_id' => $itemId]]
+        );
+        $this->galleryReadHandlerMock->expects($this->once())->method('addMediaDataToProduct')
+            ->with($itemMock, $mediaGalleriesMock);
+
+        $this->assertSame($this->collection, $this->collection->addMediaGalleryData());
+    }
+
     /**
      * @param $map
      */
diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php
index 1419c17e11b298d1fcdc554a3131d7b8c9b8ffe8..e1680ab5a4081946b73b375a85c0b53cf916afd4 100755
--- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php
+++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php
@@ -754,7 +754,10 @@ class Eav extends AbstractModifier
         $meta['arguments']['data']['config']['wysiwyg'] = true;
         $meta['arguments']['data']['config']['wysiwygConfigData'] = [
             'add_variables' => false,
-            'add_widgets' => false
+            'add_widgets' => false,
+            'add_directives' => true,
+            'use_container' => true,
+            'container_class' => 'hor-scroll',
         ];
 
         return $meta;
diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php
index c9d155177e48a588a655d603234482ac53cbe545..fa704272962162d43edd1d129c1229275614015a 100644
--- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php
+++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php
@@ -5,7 +5,6 @@
  */
 namespace Magento\CatalogImportExport\Model\Export;
 
-use Magento\Framework\DB\Ddl\Table;
 use Magento\ImportExport\Model\Import;
 use \Magento\Store\Model\Store;
 use \Magento\CatalogImportExport\Model\Import\Product as ImportProduct;
@@ -850,6 +849,24 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity
         return $writer->getContents();
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    protected function _prepareEntityCollection(\Magento\Eav\Model\Entity\Collection\AbstractCollection $collection)
+    {
+        $exportFilter = !empty($this->_parameters[\Magento\ImportExport\Model\Export::FILTER_ELEMENT_GROUP]) ?
+            $this->_parameters[\Magento\ImportExport\Model\Export::FILTER_ELEMENT_GROUP] : [];
+
+        if (isset($exportFilter['category_ids'])
+            && trim($exportFilter['category_ids'])
+            && $collection instanceof \Magento\Catalog\Model\ResourceModel\Product\Collection
+        ) {
+            $collection->addCategoriesFilter(['in' => explode(',', $exportFilter['category_ids'])]);
+        }
+
+        return parent::_prepareEntityCollection($collection);
+    }
+
     /**
      * Get export data for collection
      *
diff --git a/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php b/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php
index c5cdd1950cc3803a238bdd77caa1ee5fa2f8b88e..58e364920bb6ad4919212ba329e2d8294cd36027 100644
--- a/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php
+++ b/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php
@@ -15,13 +15,14 @@ use Magento\CatalogInventory\Model\Indexer\Stock\Processor;
 use Magento\CatalogInventory\Model\ResourceModel\Stock\Item as StockItemResource;
 use Magento\CatalogInventory\Model\Spi\StockStateProviderInterface;
 use Magento\CatalogInventory\Model\StockRegistryStorage;
+use Magento\Framework\App\ObjectManager;
 use Magento\Framework\DB\MapperFactory;
 use Magento\Framework\DB\QueryBuilderFactory;
 use Magento\Framework\Exception\CouldNotDeleteException;
 use Magento\Framework\Exception\CouldNotSaveException;
 use Magento\Framework\Exception\NoSuchEntityException;
-use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
 use Magento\Framework\Stdlib\DateTime\DateTime;
+use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
 
 /**
  * Class StockItemRepository
@@ -89,6 +90,9 @@ class StockItemRepository implements StockItemRepositoryInterface
      */
     protected $stockRegistryStorage;
 
+    /** @var  \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory */
+    protected $productCollectionFactory;
+
     /**
      * @param StockConfigurationInterface $stockConfiguration
      * @param StockStateProviderInterface $stockStateProvider
@@ -129,6 +133,21 @@ class StockItemRepository implements StockItemRepositoryInterface
         $this->dateTime = $dateTime;
     }
 
+    /**
+     * @deprecated
+     * @return  \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory
+     */
+    private function getProductCollectionFactory()
+    {
+        if ($this->productCollectionFactory === null) {
+            $this->productCollectionFactory = ObjectManager::getInstance()->get(
+                \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory::class
+            );
+        }
+
+        return $this->productCollectionFactory;
+    }
+
     /**
      * @inheritdoc
      */
@@ -136,8 +155,12 @@ class StockItemRepository implements StockItemRepositoryInterface
     {
         try {
             /** @var \Magento\Catalog\Model\Product $product */
-            $product = $this->productFactory->create();
-            $product->load($stockItem->getProductId());
+            $product = $this->getProductCollectionFactory()->create()
+                ->setFlag('has_stock_status_filter')
+                ->addIdFilter($stockItem->getProductId())
+                ->addFieldToSelect('type_id')
+                ->getFirstItem();
+
             if (!$product->getId()) {
                 return $stockItem;
             }
diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php
index 769e2db4cc84553a3a10e081e6785a02a72b5d15..23b7805e622e32938a3403e58af7f30d8a8d80e8 100644
--- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php
+++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php
@@ -5,6 +5,8 @@
  */
 namespace Magento\CatalogInventory\Test\Unit\Model\Stock;
 
+use Magento\Catalog\Model\ResourceModel\Product\Collection;
+use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
 use Magento\CatalogInventory\Model\Stock\StockItemRepository;
 use Magento\CatalogInventory\Api\Data as InventoryApiData;
 use Magento\CatalogInventory\Model\StockRegistryStorage;
@@ -153,9 +155,8 @@ class StockItemRepositoryTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->setMethods(['load', 'getId', 'getTypeId', '__wakeup'])
             ->getMock();
-        $this->productFactoryMock->expects($this->any())
-            ->method('create')
-            ->willReturn($this->productMock);
+
+        $this->productFactoryMock->expects($this->any())->method('create')->willReturn($this->productMock);
 
         $this->queryBuilderFactoryMock = $this->getMockBuilder(\Magento\Framework\DB\QueryBuilderFactory::class)
             ->setMethods(['create'])
@@ -185,6 +186,22 @@ class StockItemRepositoryTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->getMock();
 
+        $productCollection = $this->getMockBuilder(
+            \Magento\Catalog\Model\ResourceModel\Product\Collection::class
+        )->disableOriginalConstructor()->getMock();
+
+        $productCollection->expects($this->any())->method('setFlag')->willReturnSelf();
+        $productCollection->expects($this->any())->method('addIdFilter')->willReturnSelf();
+        $productCollection->expects($this->any())->method('addFieldToSelect')->willReturnSelf();
+        $productCollection->expects($this->any())->method('getFirstItem')->willReturn($this->productMock);
+
+        $productCollectionFactory = $this->getMockBuilder(CollectionFactory::class)
+            ->setMethods(['create'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $productCollectionFactory->expects($this->any())->method('create')->willReturn($productCollection);
+
         $this->model = (new ObjectManager($this))->getObject(
             StockItemRepository::class,
             [
@@ -200,6 +217,7 @@ class StockItemRepositoryTest extends \PHPUnit_Framework_TestCase
                 'indexProcessor' => $this->indexProcessorMock,
                 'dateTime' => $this->dateTime,
                 'stockRegistryStorage' => $this->stockRegistryStorage,
+                'productCollectionFactory' => $productCollectionFactory,
             ]
         );
     }
@@ -263,7 +281,6 @@ class StockItemRepositoryTest extends \PHPUnit_Framework_TestCase
         $productId = 1;
 
         $this->stockItemMock->expects($this->any())->method('getProductId')->willReturn($productId);
-        $this->productMock->expects($this->once())->method('load')->with($productId)->willReturnSelf();
         $this->productMock->expects($this->once())->method('getId')->willReturn($productId);
         $this->productMock->expects($this->once())->method('getTypeId')->willReturn('typeId');
         $this->stockConfigurationMock->expects($this->once())->method('isQty')->with('typeId')->willReturn(true);
@@ -309,7 +326,6 @@ class StockItemRepositoryTest extends \PHPUnit_Framework_TestCase
         $productId = 1;
 
         $this->stockItemMock->expects($this->any())->method('getProductId')->willReturn($productId);
-        $this->productMock->expects($this->once())->method('load')->with($productId)->willReturnSelf();
         $this->productMock->expects($this->once())->method('getId')->willReturn(null);
         $this->stockRegistryStorage->expects($this->never())->method('removeStockItem');
         $this->stockRegistryStorage->expects($this->never())->method('removeStockStatus');
@@ -325,7 +341,6 @@ class StockItemRepositoryTest extends \PHPUnit_Framework_TestCase
         $productId = 1;
 
         $this->stockItemMock->expects($this->any())->method('getProductId')->willReturn($productId);
-        $this->productMock->expects($this->once())->method('load')->with($productId)->willReturnSelf();
         $this->productMock->expects($this->once())->method('getId')->willReturn($productId);
         $this->productMock->expects($this->once())->method('getTypeId')->willReturn('typeId');
         $this->stockConfigurationMock->expects($this->once())->method('isQty')->with('typeId')->willReturn(false);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js b/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js
index 2d6fa460ef66d26d106ad9417ffdf8d3548a3d00..3ec34cd96574bc90e5b0f8bd3bf552a877444ab0 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js
@@ -44,6 +44,13 @@ define(
                         addressData.region.region_code = region['code'];
                         addressData.region.region = region['name'];
                     }
+                } else if (
+                    !addressData.region_id
+                    && countryData()[addressData.country_id]
+                    && countryData()[addressData.country_id]['regions']
+                ) {
+                    addressData.region.region_code = '';
+                    addressData.region.region = '';
                 }
                 delete addressData.region_id;
 
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js
index bee4480b0dfb1c9db669d53f5091bb1d3564237a..9a3685b212b435e8c03adb7be2cd7a182e591b87 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js
@@ -22,7 +22,7 @@ define([], function () {
         return {
             email: addressData.email,
             countryId: addressData['country_id'] || addressData.countryId || window.checkoutConfig.defaultCountryId,
-            regionId: regionId,
+            regionId: regionId || addressData.regionId,
             regionCode: (addressData.region) ? addressData.region.region_code : null,
             region: (addressData.region) ? addressData.region.region : null,
             customerId: addressData.customer_id,
@@ -30,7 +30,7 @@ define([], function () {
             company: addressData.company,
             telephone: addressData.telephone,
             fax: addressData.fax,
-            postcode: addressData.postcode ? addressData.postcode : window.checkoutConfig.defaultPostcode,
+            postcode: addressData.postcode ? addressData.postcode : window.checkoutConfig.defaultPostcode || undefined,
             city: addressData.city,
             firstname: addressData.firstname,
             lastname: addressData.lastname,
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/payment/method-group.js b/app/code/Magento/Checkout/view/frontend/web/js/model/payment/method-group.js
new file mode 100644
index 0000000000000000000000000000000000000000..4236a215d73596b918d782a2773698e5fa25234f
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/payment/method-group.js
@@ -0,0 +1,31 @@
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+define([
+        'uiElement',
+        'mage/translate'
+], function (Element, $t) {
+    'use strict';
+
+    var DEFAULT_GROUP_ALIAS = 'default';
+
+    return Element.extend({
+        defaults: {
+            alias: DEFAULT_GROUP_ALIAS,
+            title: $t('Payment Method'),
+            sortOrder: 100,
+            displayArea: 'payment-methods-items-${ $.alias }'
+        },
+
+        /**
+         * Checks if group instance is default
+         *
+         * @returns {Boolean}
+         */
+        isDefault: function () {
+            return this.alias === DEFAULT_GROUP_ALIAS;
+        }
+    });
+});
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js
index 420d50b83478a91ab38b6a333a681f119b6db49e..c49960ecfb91dec735239c8bc1cc88f7ffebfab0 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js
@@ -176,7 +176,7 @@ define(
                     address;
 
                 if (this.validateAddressData(addressFlat)) {
-                    addressFlat = $.extend(true, {}, quote.shippingAddress(), addressFlat);
+                    addressFlat = uiRegistry.get('checkoutProvider').shippingAddress;
                     address = addressConverter.formAddressDataToQuoteAddress(addressFlat);
                     selectShippingAddress(address);
                 }
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/list.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/list.js
index 18f6b8479c229326e28e9c02157d6a39e34625ee..918d305ee031b1d2c96eb6b246a765a16f6c8446 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/list.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/list.js
@@ -10,14 +10,22 @@ define([
     'Magento_Checkout/js/model/payment/method-list',
     'Magento_Checkout/js/model/payment/renderer-list',
     'uiLayout',
-    'Magento_Checkout/js/model/checkout-data-resolver'
-], function (_, ko, utils, Component, paymentMethods, rendererList, layout, checkoutDataResolver) {
+    'Magento_Checkout/js/model/checkout-data-resolver',
+    'mage/translate',
+    'uiRegistry'
+], function (_, ko, utils, Component, paymentMethods, rendererList, layout, checkoutDataResolver, $t, registry) {
     'use strict';
 
     return Component.extend({
         defaults: {
             template: 'Magento_Checkout/payment-methods/list',
-            visible: paymentMethods().length > 0
+            visible: paymentMethods().length > 0,
+            configDefaultGroup: {
+                name: 'methodGroup',
+                component: 'Magento_Checkout/js/model/payment/method-group'
+            },
+            paymentGroupsList: [],
+            defaultGroupTitle: $t('Select a new payment method')
         },
 
         /**
@@ -26,7 +34,7 @@ define([
          * @returns {Component} Chainable.
          */
         initialize: function () {
-            this._super().initChildren();
+            this._super().initDefaulGroup().initChildren();
             paymentMethods.subscribe(
                 function (changes) {
                     checkoutDataResolver.resolvePaymentMethod();
@@ -47,6 +55,27 @@ define([
             return this;
         },
 
+        /** @inheritdoc */
+        initObservable: function () {
+            this._super().
+                observe(['paymentGroupsList']);
+
+            return this;
+        },
+
+        /**
+         * Creates default group
+         *
+         * @returns {Component} Chainable.
+         */
+        initDefaulGroup: function() {
+            layout([
+                this.configDefaultGroup
+            ]);
+
+            return this;
+        },
+
         /**
          * Create renders for child payment methods.
          *
@@ -77,7 +106,7 @@ define([
             rendererTemplate = {
                 parent: '${ $.$data.parentName }',
                 name: '${ $.$data.name }',
-                displayArea: 'payment-method-items',
+                displayArea: payment.displayArea,
                 component: payment.component
             };
             rendererComponent = utils.template(rendererTemplate, templateData);
@@ -95,49 +124,105 @@ define([
          * @param {Object} paymentMethodData
          */
         createRenderer: function (paymentMethodData) {
-            var isRendererForMethod = false;
+            var isRendererForMethod = false,
+                currentGroup;
+
+            registry.get(this.configDefaultGroup.name, function (defaultGroup) {
+                _.each(rendererList(), function (renderer) {
 
-            _.find(rendererList(), function (renderer) {
+                    if (renderer.hasOwnProperty('typeComparatorCallback') &&
+                        typeof renderer.typeComparatorCallback == 'function'
+                    ) {
+                        isRendererForMethod = renderer.typeComparatorCallback(renderer.type, paymentMethodData.method);
+                    } else {
+                        isRendererForMethod = renderer.type === paymentMethodData.method;
+                    }
 
-                if (renderer.hasOwnProperty('typeComparatorCallback') &&
-                    typeof renderer.typeComparatorCallback == 'function'
-                ) {
-                    isRendererForMethod = renderer.typeComparatorCallback(renderer.type, paymentMethodData.method);
-                } else {
-                    isRendererForMethod = renderer.type === paymentMethodData.method;
-                }
+                    if (isRendererForMethod) {
+                        currentGroup = renderer.group ? renderer.group : defaultGroup;
 
-                if (isRendererForMethod) {
-                    layout(
-                        [
+                        this.collectPaymentGroups(currentGroup);
+
+                        layout([
                             this.createComponent(
                                 {
                                     config: renderer.config,
                                     component: renderer.component,
                                     name: renderer.type,
                                     method: paymentMethodData.method,
-                                    item: paymentMethodData
+                                    item: paymentMethodData,
+                                    displayArea: currentGroup.displayArea
                                 }
-                            )
-                        ]
-                    );
-                }
+                            )]);
+                    }
+                }.bind(this));
             }.bind(this));
         },
 
+        /**
+         * Collects unique groups of available payment methods
+         *
+         * @param {Object} group
+         */
+        collectPaymentGroups: function (group) {
+            var groupsList = this.paymentGroupsList(),
+                isGroupExists = _.some(groupsList, function (existsGroup) {
+                    return existsGroup.alias === group.alias;
+                });
+
+            if (!isGroupExists) {
+                groupsList.push(group);
+                groupsList = _.sortBy(groupsList, function (existsGroup) {
+                    return existsGroup.sortOrder;
+                });
+                this.paymentGroupsList(groupsList);
+            }
+        },
+
+        /**
+         * Returns payment group title
+         *
+         * @param {Object} group
+         * @returns {String}
+         */
+        getGroupTitle: function (group) {
+            var title = group().title;
+
+            if (group().isDefault() && this.paymentGroupsList().length > 1) {
+                title = this.defaultGroupTitle;
+            }
+
+            return title + ':';
+        },
+
+        /**
+         * Checks if at least one payment method available
+         *
+         * @returns {String}
+         */
+        isPaymentMethodsAvailable: function () {
+            return _.some(this.paymentGroupsList(), function (group) {
+                return this.getRegion(group.displayArea)().length;
+            }, this);
+        },
+
         /**
          * Remove view renderer.
          *
          * @param {String} paymentMethodCode
          */
         removeRenderer: function (paymentMethodCode) {
-            var items = this.getRegion('payment-method-items');
+            var items;
+
+            _.each(this.paymentGroupsList(), function (group) {
+                items = this.getRegion(group.displayArea);
 
-            _.find(items(), function (value) {
-                if (value.item.method.indexOf(paymentMethodCode) === 0) {
-                    value.disposeSubscriptions();
-                    value.destroy();
-                }
+                _.find(items(), function (value) {
+                    if (value.item.method.indexOf(paymentMethodCode) === 0) {
+                        value.disposeSubscriptions();
+                        value.destroy();
+                    }
+                });
             }, this);
         }
     });
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html
index f45115181fe4c628c88d3b5a26129629c21415b5..da625c51d4b7734ccc4808fd9161502e15acf1a9 100644
--- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html
@@ -13,6 +13,11 @@
     <!-- ko if: (currentBillingAddress().telephone) -->
     <a data-bind="text: currentBillingAddress().telephone, attr: {'href': 'tel:' + currentBillingAddress().telephone}"></a>
     <!-- /ko --><br/>
+    <!-- ko foreach: { data: currentBillingAddress().customAttributes, as: 'element' } -->
+        <!-- ko foreach: { data: Object.keys(element), as: 'attribute' } -->
+            <!-- ko text: element[attribute].value --><!-- /ko -->
+        <!-- /ko -->
+    <!-- /ko -->
     <button type="button"
             class="action action-edit-address"
             data-bind="visible: !isAddressSameAsShipping(), click: editAddress">
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/payment-methods/list.html b/app/code/Magento/Checkout/view/frontend/web/template/payment-methods/list.html
index 66769f37386d6402c3d71d19f7f08ef6d88ca8b7..f6c41c62eeca62fcd89e0d85715863806d95e9f8 100644
--- a/app/code/Magento/Checkout/view/frontend/web/template/payment-methods/list.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/payment-methods/list.html
@@ -4,9 +4,19 @@
  * See COPYING.txt for license details.
  */
  -->
-<div class="items payment-methods">
-    <!-- ko foreach: { data: getRegion('payment-method-items'), as: 'element'}  -->
-        <!-- ko template: element.getTemplate() --><!-- /ko -->
-    <!-- /ko -->
+<div if="isPaymentMethodsAvailable()"
+     class="items payment-methods">
+    <div repeat="foreach: paymentGroupsList, item: '$group'"
+         class="payment-group">
+        <div if="getRegion($group().displayArea)().length"
+             translate="getGroupTitle($group)"
+             class="step-title"
+             data-role="title">
+        </div>
+        <each args="data: getRegion($group().displayArea), as: 'method'" render=""/>
+    </div>
+</div>
+<div ifnot="isPaymentMethodsAvailable()"
+     class="no-payments-block"
+     translate="'No Payment Methods'">
 </div>
-<!-- ko ifnot: getRegion('payment-method-items')().length > 0 --><div class="no-payments-block"><!-- ko i18n: 'No Payment Methods'--><!-- /ko --></div><!-- /ko -->
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/payment.html b/app/code/Magento/Checkout/view/frontend/web/template/payment.html
index 292ece611e6b664f04c4ee78a8ace01d03fb49f5..46467839da3fb08eb994d61b0d2aaa48912ada87 100644
--- a/app/code/Magento/Checkout/view/frontend/web/template/payment.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/payment.html
@@ -5,7 +5,6 @@
  */
 -->
 <li id="payment" role="presentation" class="checkout-payment-method" data-bind="fadeVisible: isVisible">
-    <div class="step-title" data-bind="i18n: title" data-role="title"></div>
     <div id="checkout-step-payment"
          class="step-content"
          data-role="content"
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html
index eeecbf346636613366db1f9d3fa33c4c7835b681..a2b83ead6b354451b99a4a1003a0f04df905dbbc 100644
--- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html
@@ -13,6 +13,11 @@
     <!-- ko if: (address().telephone) -->
     <a data-bind="text: address().telephone, attr: {'href': 'tel:' + address().telephone}"></a>
     <!-- /ko --><br/>
+    <!-- ko foreach: { data: address().customAttributes, as: 'element' } -->
+        <!-- ko foreach: { data: Object.keys(element), as: 'attribute' } -->
+            <!-- ko text: element[attribute].value --><!-- /ko -->
+        <!-- /ko -->
+    <!-- /ko -->
     <!-- ko if: (address().isEditable()) -->
     <button type="button"
             class="action edit-address-link"
diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html
index f02eef5ded99ab86bb3a445f7de3355f810e94e8..440a2c7fc468fc493d10eb0cb57320c5593e1bf8 100644
--- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html
+++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html
@@ -13,4 +13,9 @@
     <!-- ko if: (address().telephone) -->
     <a data-bind="text: address().telephone, attr: {'href': 'tel:' + address().telephone}"></a>
     <!-- /ko --><br/>
+    <!-- ko foreach: { data: address().customAttributes, as: 'element' } -->
+        <!-- ko foreach: { data: Object.keys(element), as: 'attribute' } -->
+            <!-- ko text: element[attribute].value --><!-- /ko -->
+        <!-- /ko -->
+    <!-- /ko -->
 <!-- /ko -->
diff --git a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurations.php b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurations.php
index ea24235b0fe2ef694e2087f7a8bdbf4c8ece3399..cb9a6b534609f7205f2c8a569b022389e13436b7 100644
--- a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurations.php
+++ b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurations.php
@@ -32,7 +32,7 @@ class UpdateConfigurations
         'swatch_image',
         'small_image',
         'thumbnail',
-        'image'
+        'image',
     ];
 
     /**
@@ -65,13 +65,15 @@ class UpdateConfigurations
     ) {
         $configurations = $this->getConfigurations();
         $configurations = $this->variationHandler->duplicateImagesForVariations($configurations);
-        foreach ($configurations as $productId => $productData) {
-            /** @var \Magento\Catalog\Model\Product $product */
-            $product = $this->productRepository->getById($productId, false, $this->request->getParam('store', 0));
-            $productData = $this->variationHandler->processMediaGallery($product, $productData);
-            $product->addData($productData);
-            if ($product->hasDataChanges()) {
-                $product->save();
+        if (count($configurations)) {
+            foreach ($configurations as $productId => $productData) {
+                /** @var \Magento\Catalog\Model\Product $product */
+                $product = $this->productRepository->getById($productId, false, $this->request->getParam('store', 0));
+                $productData = $this->variationHandler->processMediaGallery($product, $productData);
+                $product->addData($productData);
+                if ($product->hasDataChanges()) {
+                    $product->save();
+                }
             }
         }
         return $configurableProduct;
@@ -91,6 +93,12 @@ class UpdateConfigurations
         }
 
         foreach ($configurableMatrix as $item) {
+            if (empty($item['was_changed'])) {
+                continue;
+            } else {
+                unset($item['was_changed']);
+            }
+
             if (!$item['newProduct']) {
                 $result[$item['id']] = $this->mapData($item);
 
diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php b/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php
index 321870b96d32abf13c48fdc0975efc9ba5248f17..0d0bba60a7777c75deef4bc9e0a41720b9597163 100644
--- a/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php
+++ b/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php
@@ -29,6 +29,9 @@ class VariationHandler
     /** @var \Magento\Catalog\Model\ProductFactory */
     protected $productFactory;
 
+    /** @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute[] */
+    private $attributes;
+
     /**
      * @var \Magento\CatalogInventory\Api\StockConfigurationInterface
      * @deprecated
@@ -70,6 +73,7 @@ class VariationHandler
     public function generateSimpleProducts($parentProduct, $productsData)
     {
         $generatedProductIds = [];
+        $this->attributes = null;
         $productsData = $this->duplicateImagesForVariations($productsData);
         foreach ($productsData as $simpleProductData) {
             $newSimpleProduct = $this->productFactory->create();
@@ -160,7 +164,10 @@ class VariationHandler
             $parentProduct->getNewVariationsAttributeSetId()
         );
 
-        foreach ($product->getTypeInstance()->getSetAttributes($product) as $attribute) {
+        if ($this->attributes === null) {
+            $this->attributes = $product->getTypeInstance()->getSetAttributes($product);
+        }
+        foreach ($this->attributes as $attribute) {
             if ($attribute->getIsUnique() ||
                 $attribute->getAttributeCode() == 'url_key' ||
                 $attribute->getFrontend()->getInputType() == 'gallery' ||
diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurationsTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurationsTest.php
index bed5c96b5216eb76344e9ce593ea56056be9a35b..def49f42fa960b738fe952be4a2d18bada61ffd2 100644
--- a/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurationsTest.php
+++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurationsTest.php
@@ -90,13 +90,24 @@ class UpdateConfigurationsTest extends \PHPUnit_Framework_TestCase
                 'swatch_image' => 'simple2_swatch_image',
                 'small_image' => 'simple2_small_image',
                 'thumbnail' => 'simple2_thumbnail',
-                'image' => 'simple2_image'
+                'image' => 'simple2_image',
+                'was_changed' => true,
             ],
             [
                 'newProduct' => false,
                 'id' => 'product3',
-                'qty' => '3'
-            ]
+                'qty' => '3',
+                'was_changed' => true,
+            ],
+            [
+                'newProduct' => false,
+                'id' => 'product4',
+                'status' => 'simple4_status',
+                'sku' => 'simple2_sku',
+                'name' => 'simple2_name',
+                'price' => '3.33',
+                'weight' => '5.55',
+            ],
         ];
         $configurations = [
             'product2' => [
@@ -118,8 +129,8 @@ class UpdateConfigurationsTest extends \PHPUnit_Framework_TestCase
         ];
         /** @var Product[]|\PHPUnit_Framework_MockObject_MockObject[] $productMocks */
         $productMocks = [
-            'product2' => $this->getProductMock($configurations['product2'], true),
-            'product3' => $this->getProductMock($configurations['product3'])
+            'product2' => $this->getProductMock($configurations['product2'], true, true),
+            'product3' => $this->getProductMock($configurations['product3'], false, true),
         ];
 
         $this->requestMock->expects(static::any())
@@ -161,26 +172,27 @@ class UpdateConfigurationsTest extends \PHPUnit_Framework_TestCase
      * @param bool $hasDataChanges
      * @return Product|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected function getProductMock(array $expectedData = null, $hasDataChanges = false)
+    protected function getProductMock(array $expectedData = null, $hasDataChanges = false, $wasChanged = false)
     {
         $productMock = $this->getMockBuilder(Product::class)
             ->disableOriginalConstructor()
             ->getMock();
 
-        if ($expectedData !== null) {
-            $productMock->expects(static::once())
-                ->method('addData')
-                ->with($expectedData)
+        if ($wasChanged !== false) {
+            if ($expectedData !== null) {
+                $productMock->expects(static::once())
+                    ->method('addData')
+                    ->with($expectedData)
+                    ->willReturnSelf();
+            }
+
+            $productMock->expects(static::any())
+                ->method('hasDataChanges')
+                ->willReturn($hasDataChanges);
+            $productMock->expects($hasDataChanges ? static::once() : static::never())
+                ->method('save')
                 ->willReturnSelf();
         }
-
-        $productMock->expects(static::any())
-            ->method('hasDataChanges')
-            ->willReturn($hasDataChanges);
-        $productMock->expects($hasDataChanges ? static::once() : static::never())
-            ->method('save')
-            ->willReturnSelf();
-
         return $productMock;
     }
 }
diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js
index ffabd9a8627dfca82da9b87ebd84c799086d9edf..c182d9f8216c09a42868eb487dfa06b0e718b5c7 100644
--- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js
+++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js
@@ -391,11 +391,11 @@ define([
                     'small_image': row['small_image'],
                     image: row.image,
                     'thumbnail': row.thumbnail,
-                    'attributes': attributesText
+                    'attributes': attributesText,
+                    'was_changed': true
                 };
                 product[this.canEditField] = row.editable;
                 product[this.newProductField] = row.newProduct;
-
                 tmpArray.push(product);
             }, this);
 
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
index 4f13ee75bfe32c29ae544c19e950691ead763323..0d8d18df223767b2812f58356de3b7904090d8f7 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
@@ -6,8 +6,8 @@
 
 namespace Magento\Eav\Model\Entity\Attribute;
 
-use Magento\Framework\Exception\LocalizedException;
 use Magento\Framework\Api\AttributeValueFactory;
+use Magento\Framework\Exception\LocalizedException;
 
 /**
  * Entity/Attribute/Model - attribute abstract
@@ -595,11 +595,10 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
     {
         /** @var array $emptyStringTypes list of attribute types that treat empty string as a possible value */
         $emptyStringTypes = ['int', 'decimal', 'datetime', 'varchar', 'text', 'static'];
-        $attributeType = $this->getBackend()->getType();
         return (is_array($value) && count($value) == 0)
             || $value === null
-            || ($value === false && $attributeType != 'int')
-            || ($value === '' && in_array($attributeType, $emptyStringTypes));
+            || ($value === false && $this->getBackend()->getType() != 'int')
+            || ($value === '' && in_array($this->getBackend()->getType(), $emptyStringTypes));
     }
 
     /**
diff --git a/app/code/Magento/Eav/Model/ResourceModel/AttributeLoader.php b/app/code/Magento/Eav/Model/ResourceModel/AttributeLoader.php
new file mode 100644
index 0000000000000000000000000000000000000000..439f550a2bf020fadd8ae18abfb2348f4b18cf6b
--- /dev/null
+++ b/app/code/Magento/Eav/Model/ResourceModel/AttributeLoader.php
@@ -0,0 +1,97 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Eav\Model\ResourceModel;
+
+use Magento\Eav\Api\AttributeRepositoryInterface as AttributeRepository;
+use Magento\Eav\Model\Entity\AttributeCache;
+use Magento\Framework\Api\SearchCriteriaBuilder;
+use Magento\Framework\EntityManager\MetadataPool;
+
+/**
+ * Сlass responsible for loading and caching of attributes related to the given attribute set.
+ *
+ * Can be used to improve performance of services that mostly read attribute data.
+ */
+class AttributeLoader
+{
+    /** Name of ATTRIBUTE_SET_ID field */
+    const ATTRIBUTE_SET_ID = 'attribute_set_id';
+
+    /**
+     * @var AttributeRepository
+     */
+    private $attributeRepository;
+
+    /**
+     * @var MetadataPool
+     */
+    private $metadataPool;
+
+    /**
+     * @var SearchCriteriaBuilder
+     */
+    private $searchCriteriaBuilder;
+
+    /**
+     * @var AttributeCache
+     */
+    private $attributeCache;
+
+    /**
+     * AttributeLoader constructor.
+     * @param AttributeRepository $attributeRepository
+     * @param MetadataPool $metadataPool
+     * @param SearchCriteriaBuilder $searchCriteriaBuilder
+     * @param AttributeCache $attributeCache
+     */
+    public function __construct(
+        AttributeRepository $attributeRepository,
+        MetadataPool $metadataPool,
+        SearchCriteriaBuilder $searchCriteriaBuilder,
+        AttributeCache $attributeCache
+    ) {
+        $this->attributeRepository = $attributeRepository;
+        $this->metadataPool = $metadataPool;
+        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
+        $this->attributeCache = $attributeCache;
+    }
+
+    /**
+     * Get attributes list from attribute set
+     *
+     * @param string $entityType
+     * @param int $attributeSetId
+     * @return \Magento\Eav\Api\Data\AttributeInterface[]|\object[]
+     */
+    public function getAttributes($entityType, $attributeSetId = null)
+    {
+        $suffix =  self::ATTRIBUTE_SET_ID . '-' . ($attributeSetId ?: 'all');
+        if ($attributes = $this->attributeCache->getAttributes($entityType, $suffix)) {
+            return $attributes;
+        }
+
+        $metadata = $this->metadataPool->getMetadata($entityType);
+
+        if ($attributeSetId === null) {
+            $criteria = $this->searchCriteriaBuilder->addFilter(self::ATTRIBUTE_SET_ID, null, 'neq')->create();
+        } else {
+            $criteria = $this->searchCriteriaBuilder->addFilter(self::ATTRIBUTE_SET_ID, $attributeSetId)->create();
+        }
+
+        $searchResult = $this->attributeRepository->getList(
+            $metadata->getEavEntityType(),
+            $criteria
+        );
+        $attributes = $searchResult->getItems();
+
+        $this->attributeCache->saveAttributes(
+            $entityType,
+            $attributes,
+            $suffix
+        );
+        return $attributes;
+    }
+}
diff --git a/app/code/Magento/Eav/Model/ResourceModel/AttributePersistor.php b/app/code/Magento/Eav/Model/ResourceModel/AttributePersistor.php
index 74373cb593c4086c06378050e1fa89b944d78be6..5e340595df9867b1cb02fd795c6fc9be7e34fc02 100644
--- a/app/code/Magento/Eav/Model/ResourceModel/AttributePersistor.php
+++ b/app/code/Magento/Eav/Model/ResourceModel/AttributePersistor.php
@@ -113,13 +113,14 @@ class AttributePersistor
             return;
         }
         $metadata = $this->metadataPool->getMetadata($entityType);
+        $linkField = $metadata->getLinkField();
         foreach ($this->delete[$entityType] as $link => $data) {
             $attributeCodes = array_keys($data);
             foreach ($attributeCodes as $attributeCode) {
                 /** @var AbstractAttribute $attribute */
                 $attribute = $this->attributeRepository->get($metadata->getEavEntityType(), $attributeCode);
                 $conditions = [
-                    $metadata->getLinkField() . ' = ?' => $link,
+                    $linkField . ' = ?' => $link,
                     'attribute_id = ?' => $attribute->getAttributeId()
                 ];
                 foreach ($context as $scope) {
@@ -147,6 +148,7 @@ class AttributePersistor
             return;
         }
         $metadata = $this->metadataPool->getMetadata($entityType);
+        $linkField = $metadata->getLinkField();
         foreach ($this->insert[$entityType] as $link => $data) {
             foreach ($data as $attributeCode => $attributeValue) {
                 /** @var AbstractAttribute $attribute */
@@ -155,7 +157,7 @@ class AttributePersistor
                     $attributeCode
                 );
                 $data = [
-                    $metadata->getLinkField() => $link,
+                    $linkField => $link,
                     'attribute_id' => $attribute->getAttributeId(),
                     'value' => $this->prepareValue($entityType, $attributeValue, $attribute)
                 ];
@@ -180,6 +182,7 @@ class AttributePersistor
             return;
         }
         $metadata = $this->metadataPool->getMetadata($entityType);
+        $linkField = $metadata->getLinkField();
         foreach ($this->update[$entityType] as $link => $data) {
             foreach ($data as $attributeCode => $attributeValue) {
                 /** @var AbstractAttribute $attribute */
@@ -188,7 +191,7 @@ class AttributePersistor
                     $attributeCode
                 );
                 $conditions = [
-                    $metadata->getLinkField() . ' = ?' => $link,
+                    $linkField . ' = ?' => $link,
                     'attribute_id = ?' => $attribute->getAttributeId(),
                 ];
                 foreach ($context as $scope) {
diff --git a/app/code/Magento/Eav/Model/ResourceModel/CreateHandler.php b/app/code/Magento/Eav/Model/ResourceModel/CreateHandler.php
index 1a8aaaf027f561966101e360020fb3a2441e27d6..df411b6a21698033c60839c0d855c3b0ed4e96e5 100644
--- a/app/code/Magento/Eav/Model/ResourceModel/CreateHandler.php
+++ b/app/code/Magento/Eav/Model/ResourceModel/CreateHandler.php
@@ -6,9 +6,10 @@
 namespace Magento\Eav\Model\ResourceModel;
 
 use Magento\Eav\Api\AttributeRepositoryInterface as AttributeRepository;
-use Magento\Framework\EntityManager\Operation\AttributeInterface;
-use Magento\Framework\EntityManager\MetadataPool;
 use Magento\Framework\Api\SearchCriteriaBuilder;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\EntityManager\MetadataPool;
+use Magento\Framework\EntityManager\Operation\AttributeInterface;
 use Magento\Framework\Model\Entity\ScopeResolver;
 
 /**
@@ -42,40 +43,43 @@ class CreateHandler implements AttributeInterface
      */
     private $scopeResolver;
 
+    /**
+     * @var AttributeLoader
+     */
+    private $attributeLoader;
+
     /**
      * @param AttributeRepository $attributeRepository
      * @param MetadataPool $metadataPool
      * @param SearchCriteriaBuilder $searchCriteriaBuilder
      * @param AttributePersistor $attributePersistor
      * @param ScopeResolver $scopeResolver
+     * @param AttributeLoader $attributeLoader
      */
     public function __construct(
         AttributeRepository $attributeRepository,
         MetadataPool $metadataPool,
         SearchCriteriaBuilder $searchCriteriaBuilder,
         AttributePersistor $attributePersistor,
-        ScopeResolver $scopeResolver
+        ScopeResolver $scopeResolver,
+        AttributeLoader $attributeLoader = null
     ) {
         $this->attributeRepository = $attributeRepository;
         $this->metadataPool = $metadataPool;
         $this->searchCriteriaBuilder = $searchCriteriaBuilder;
         $this->attributePersistor = $attributePersistor;
         $this->scopeResolver = $scopeResolver;
+        $this->attributeLoader = $attributeLoader ?: ObjectManager::getInstance()->get(AttributeLoader::class);
     }
 
     /**
      * @param string $entityType
+     * @param int $attributeSetId
      * @return \Magento\Eav\Api\Data\AttributeInterface[]
-     * @throws \Exception
      */
-    protected function getAttributes($entityType)
+    protected function getAttributes($entityType, $attributeSetId = null)
     {
-        $metadata = $this->metadataPool->getMetadata($entityType);
-        $searchResult = $this->attributeRepository->getList(
-            $metadata->getEavEntityType(),
-            $this->searchCriteriaBuilder->addFilter('attribute_set_id', null, 'neq')->create()
-        );
-        return $searchResult->getItems();
+        return $this->attributeLoader->getAttributes($entityType, $attributeSetId);
     }
 
     /**
@@ -92,23 +96,28 @@ class CreateHandler implements AttributeInterface
         $metadata = $this->metadataPool->getMetadata($entityType);
         if ($metadata->getEavEntityType()) {
             $processed = [];
+            $entityLinkField = $metadata->getLinkField();
+            $attributeSetId = isset($entityData[AttributeLoader::ATTRIBUTE_SET_ID])
+                ? $entityData[AttributeLoader::ATTRIBUTE_SET_ID]
+                : null; // @todo verify is it normal to not have attributer_set_id
             /** @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute */
-            foreach ($this->getAttributes($entityType) as $attribute) {
+            foreach ($this->getAttributes($entityType, $attributeSetId) as $attribute) {
                 if ($attribute->isStatic()) {
                     continue;
                 }
-                if (isset($entityData[$attribute->getAttributeCode()])
-                    && !is_array($entityData[$attribute->getAttributeCode()])
-                    && !$attribute->isValueEmpty($entityData[$attribute->getAttributeCode()])
+
+                $attributeCode = $attribute->getAttributeCode();
+                if (isset($entityData[$attributeCode])
+                    && !is_array($entityData[$attributeCode])
+                    && !$attribute->isValueEmpty($entityData[$attributeCode])
                 ) {
-                    $entityLinkField = $metadata->getLinkField();
                     $this->attributePersistor->registerInsert(
                         $entityType,
                         $entityData[$entityLinkField],
-                        $attribute->getAttributeCode(),
-                        $entityData[$attribute->getAttributeCode()]
+                        $attributeCode,
+                        $entityData[$attributeCode]
                     );
-                    $processed[$attribute->getAttributeCode()] = $entityData[$attribute->getAttributeCode()];
+                    $processed[$attributeCode] = $entityData[$attributeCode];
                 }
             }
             $context = $this->scopeResolver->getEntityContext($entityType, $entityData);
diff --git a/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php b/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php
index 0f892a272fa1a209ca7b2e632abc98db5afb5d3d..c775a24a03c465dad45640a7f634823cb8b43ef8 100644
--- a/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php
+++ b/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php
@@ -54,6 +54,11 @@ class UpdateHandler implements AttributeInterface
      */
     private $readHandler;
 
+    /**
+     * @var AttributeLoader
+     */
+    private $attributeLoader;
+
     /**
      * UpdateHandler constructor.
      * @param AttributeRepository $attributeRepository
@@ -62,6 +67,7 @@ class UpdateHandler implements AttributeInterface
      * @param AttributePersistor $attributePersistor
      * @param ReadSnapshot $readSnapshot
      * @param ScopeResolver $scopeResolver
+     * @param AttributeLoader $attributeLoader
      */
     public function __construct(
         AttributeRepository $attributeRepository,
@@ -69,7 +75,8 @@ class UpdateHandler implements AttributeInterface
         SearchCriteriaBuilder $searchCriteriaBuilder,
         AttributePersistor $attributePersistor,
         ReadSnapshot $readSnapshot,
-        ScopeResolver $scopeResolver
+        ScopeResolver $scopeResolver,
+        AttributeLoader $attributeLoader = null
     ) {
         $this->attributeRepository = $attributeRepository;
         $this->metadataPool = $metadataPool;
@@ -77,22 +84,17 @@ class UpdateHandler implements AttributeInterface
         $this->attributePersistor = $attributePersistor;
         $this->readSnapshot = $readSnapshot;
         $this->scopeResolver = $scopeResolver;
+        $this->attributeLoader = $attributeLoader ?: ObjectManager::getInstance()->get(AttributeLoader::class);
     }
 
     /**
      * @param string $entityType
+     * @param int $attributeSetId
      * @return \Magento\Eav\Api\Data\AttributeInterface[]
-     * @throws \Exception
      */
-    protected function getAttributes($entityType)
+    protected function getAttributes($entityType, $attributeSetId = null)
     {
-        $metadata = $this->metadataPool->getMetadata($entityType);
-
-        $searchResult = $this->attributeRepository->getList(
-            $metadata->getEavEntityType(),
-            $this->searchCriteriaBuilder->addFilter('attribute_set_id', null, 'neq')->create()
-        );
-        return $searchResult->getItems();
+        return $this->attributeLoader->getAttributes($entityType, $attributeSetId);
     }
 
     /**
@@ -118,8 +120,11 @@ class UpdateHandler implements AttributeInterface
                     $entityDataForSnapshot[$scope->getIdentifier()] = $entityData[$scope->getIdentifier()];
                 }
             }
+            $attributeSetId = isset($entityData[AttributeLoader::ATTRIBUTE_SET_ID])
+                ? $entityData[AttributeLoader::ATTRIBUTE_SET_ID]
+                : null; // @todo verify is it normal to not have attributer_set_id
             $snapshot = $this->readSnapshot->execute($entityType, $entityDataForSnapshot);
-            foreach ($this->getAttributes($entityType) as $attribute) {
+            foreach ($this->getAttributes($entityType, $attributeSetId) as $attribute) {
                 if ($attribute->isStatic()) {
                     continue;
                 }
diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php
index d6b88e0ac56915c3b116ac740b18cfd31ae9f876..a10bafacda42dc2b72fcc285307a0250cae3074b 100644
--- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php
+++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php
@@ -207,7 +207,7 @@ class AbstractAttributeTest extends \PHPUnit_Framework_TestCase
             ]
         );
         $backendModelMock->expects($this->any())->method('getType')->willReturn($attributeType);
-        $model->expects($this->once())->method('getBackend')->willReturn($backendModelMock);
+        $model->expects($this->any())->method('getBackend')->willReturn($backendModelMock);
         $this->assertEquals($isEmpty, $model->isValueEmpty($value));
     }
 
diff --git a/app/code/Magento/PageCache/etc/events.xml b/app/code/Magento/PageCache/etc/events.xml
index 7ac67a931c7ac8bbbe3b5e397a7ade7b3a039633..8d88feeab18bca0ef4101933f54335d51eed2129 100644
--- a/app/code/Magento/PageCache/etc/events.xml
+++ b/app/code/Magento/PageCache/etc/events.xml
@@ -48,11 +48,6 @@
     <event name="model_save_commit_after">
         <observer name="flush_cache_after_model_save" instance="Magento\PageCache\Observer\FlushCacheByTags" />
     </event>
-    <event name="controller_action_predispatch">
-        <observer name="register_form_key"
-                  instance="Magento\PageCache\Observer\RegisterFormKeyFromCookie"
-                  />
-    </event>
     <event name="customer_logout">
         <observer name="FlushFormKeyOnLogout" instance="Magento\PageCache\Observer\FlushFormKeyOnLogout"/>
     </event>
diff --git a/app/code/Magento/PageCache/etc/frontend/events.xml b/app/code/Magento/PageCache/etc/frontend/events.xml
new file mode 100644
index 0000000000000000000000000000000000000000..10ef2eee02804fea57163ea4103cede60a01d220
--- /dev/null
+++ b/app/code/Magento/PageCache/etc/frontend/events.xml
@@ -0,0 +1,12 @@
+<?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="urn:magento:framework:Event/etc/events.xsd">
+    <event name="controller_action_predispatch">
+        <observer name="register_form_key" instance="Magento\PageCache\Observer\RegisterFormKeyFromCookie" />
+    </event>
+</config>
diff --git a/app/code/Magento/Paypal/Model/Payflow/Transparent.php b/app/code/Magento/Paypal/Model/Payflow/Transparent.php
index b5803c5ace3925b75e81df43992f714a74ed9905..f65edd71daa5b82b5191cd20a7f01a4b90b79b8c 100644
--- a/app/code/Magento/Paypal/Model/Payflow/Transparent.php
+++ b/app/code/Magento/Paypal/Model/Payflow/Transparent.php
@@ -186,6 +186,7 @@ class Transparent extends Payflowpro implements TransparentInterface
         $this->createPaymentToken($payment, $token);
 
         $payment->unsAdditionalInformation(self::CC_DETAILS);
+        $payment->unsAdditionalInformation(self::PNREF);
 
         return $this;
     }
diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/TransparentTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/TransparentTest.php
index 2d757147cec6a89dc1b6b6b28f283fd29b98f640..e2d5d348dda2cf96da1789806a43814c8960c49a 100644
--- a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/TransparentTest.php
+++ b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/TransparentTest.php
@@ -428,6 +428,13 @@ class TransparentTest extends \PHPUnit_Framework_TestCase
             ->method('setVaultPaymentToken')
             ->with($paymentTokenMock);
 
+        $this->paymentMock->expects($this->at(8))
+            ->method('unsAdditionalInformation')
+            ->with(Transparent::CC_DETAILS);
+        $this->paymentMock->expects($this->at(9))
+            ->method('unsAdditionalInformation')
+            ->with(Transparent::PNREF);
+
         $this->assertSame($this->object, $this->object->authorize($this->paymentMock, 33));
     }
 }
diff --git a/app/code/Magento/Quote/Model/Quote.php b/app/code/Magento/Quote/Model/Quote.php
index 3cdcf70cf24266ae7613e7e6f790c4b6777ff23b..f84ca33b436f91e4afca6cae6f52c8b975cf4289 100644
--- a/app/code/Magento/Quote/Model/Quote.php
+++ b/app/code/Magento/Quote/Model/Quote.php
@@ -2157,6 +2157,12 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C
     {
         if (!$this->getReservedOrderId()) {
             $this->setReservedOrderId($this->_getResource()->getReservedOrderId($this));
+        } else {
+            //checking if reserved order id was already used for some order
+            //if yes reserving new one if not using old one
+            if ($this->_getResource()->isOrderIncrementIdUsed($this->getReservedOrderId())) {
+                $this->setReservedOrderId($this->_getResource()->getReservedOrderId($this));
+            }
         }
         return $this;
     }
diff --git a/app/code/Magento/Quote/Model/Quote/Address/Total/Shipping.php b/app/code/Magento/Quote/Model/Quote/Address/Total/Shipping.php
index f1660c9f9d6427fb617c2de9d87ae2a8026be3aa..7d8946661476cb851f2488405708847530e99673 100644
--- a/app/code/Magento/Quote/Model/Quote/Address/Total/Shipping.php
+++ b/app/code/Magento/Quote/Model/Quote/Address/Total/Shipping.php
@@ -59,10 +59,8 @@ class Shipping extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal
 
         $addressWeight = $address->getWeight();
         $freeMethodWeight = $address->getFreeMethodWeight();
+        $addressFreeShipping = $address->getFreeShipping();
 
-        $address->setFreeShipping(
-            $this->freeShipping->isFreeShipping($quote, $shippingAssignment->getItems())
-        );
         $total->setTotalAmount($this->getCode(), 0);
         $total->setBaseTotalAmount($this->getCode(), 0);
 
@@ -98,7 +96,7 @@ class Shipping extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal
                         $itemQty = $child->getTotalQty();
                         $rowWeight = $itemWeight * $itemQty;
                         $addressWeight += $rowWeight;
-                        if ($address->getFreeShipping() || $child->getFreeShipping() === true) {
+                        if ($addressFreeShipping || $child->getFreeShipping() === true) {
                             $rowWeight = 0;
                         } elseif (is_numeric($child->getFreeShipping())) {
                             $freeQty = $child->getFreeShipping();
@@ -116,7 +114,7 @@ class Shipping extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal
                     $itemWeight = $item->getWeight();
                     $rowWeight = $itemWeight * $item->getQty();
                     $addressWeight += $rowWeight;
-                    if ($address->getFreeShipping() || $item->getFreeShipping() === true) {
+                    if ($addressFreeShipping || $item->getFreeShipping() === true) {
                         $rowWeight = 0;
                     } elseif (is_numeric($item->getFreeShipping())) {
                         $freeQty = $item->getFreeShipping();
@@ -136,7 +134,7 @@ class Shipping extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal
                 $itemWeight = $item->getWeight();
                 $rowWeight = $itemWeight * $item->getQty();
                 $addressWeight += $rowWeight;
-                if ($address->getFreeShipping() || $item->getFreeShipping() === true) {
+                if ($addressFreeShipping || $item->getFreeShipping() === true) {
                     $rowWeight = 0;
                 } elseif (is_numeric($item->getFreeShipping())) {
                     $freeQty = $item->getFreeShipping();
@@ -157,6 +155,10 @@ class Shipping extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal
 
         $address->setWeight($addressWeight);
         $address->setFreeMethodWeight($freeMethodWeight);
+        $address->setFreeShipping(
+            $this->freeShipping->isFreeShipping($quote, $shippingAssignment->getItems())
+        );
+
         $address->collectShippingRates();
 
         if ($method) {
diff --git a/app/code/Magento/Quote/Model/ResourceModel/Quote.php b/app/code/Magento/Quote/Model/ResourceModel/Quote.php
index 241f0d6b272fc33f6b29ff4e2c069ca088c5073b..6113a1ba56ac184d59a6d0e37bd696455dce31cd 100644
--- a/app/code/Magento/Quote/Model/ResourceModel/Quote.php
+++ b/app/code/Magento/Quote/Model/ResourceModel/Quote.php
@@ -172,6 +172,29 @@ class Quote extends AbstractDb
         ->getNextValue();
     }
 
+    /**
+     * Check if order increment ID is already used.
+     * Method can be used to avoid collisions of order IDs.
+     *
+     * @param int $orderIncrementId
+     * @return bool
+     */
+    public function isOrderIncrementIdUsed($orderIncrementId)
+    {
+        /** @var  \Magento\Framework\DB\Adapter\AdapterInterface $adapter */
+        $adapter = $this->getConnection();
+        $bind = [':increment_id' => $orderIncrementId];
+        /** @var \Magento\Framework\DB\Select $select */
+        $select = $adapter->select();
+        $select->from($this->getTable('sales_order'), 'entity_id')->where('increment_id = :increment_id');
+        $entity_id = $adapter->fetchOne($select, $bind);
+        if ($entity_id > 0) {
+            return true;
+        }
+
+        return false;
+    }
+
     /**
      * Mark quotes - that depend on catalog price rules - to be recollected on demand
      *
diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php
index 5165f299d45a96b7aa9b130a03747fad38955084..b54ce84fe1ac45fbee2d1b2c89a99c8546a11cab 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php
@@ -314,7 +314,10 @@ class QuoteTest extends \PHPUnit_Framework_TestCase
                     'customerRepository' => $this->customerRepositoryMock,
                     'objectCopyService' => $this->objectCopyServiceMock,
                     'extensionAttributesJoinProcessor' => $this->extensionAttributesJoinProcessorMock,
-                    'customerDataFactory' => $this->customerDataFactoryMock
+                    'customerDataFactory' => $this->customerDataFactoryMock,
+                    'data' => [
+                        'reserved_order_id' => 1000001
+                    ]
                 ]
             );
     }
@@ -1237,4 +1240,30 @@ class QuoteTest extends \PHPUnit_Framework_TestCase
 
         $this->assertEquals($itemResult, $this->quote->getAllItems());
     }
+
+    /**
+     * Test to verify if existing reserved_order_id in use
+     *
+     * @param bool $isReservedOrderIdExist
+     * @param int $reservedOrderId
+     * @dataProvider reservedOrderIdDataProvider
+     */
+    public function testReserveOrderId($isReservedOrderIdExist, $reservedOrderId)
+    {
+        $this->resourceMock
+            ->expects($this->once())
+            ->method('isOrderIncrementIdUsed')
+            ->with(1000001)->willReturn($isReservedOrderIdExist);
+        $this->resourceMock->expects($this->any())->method('getReservedOrderId')->willReturn($reservedOrderId);
+        $this->quote->reserveOrderId();
+        $this->assertEquals($reservedOrderId, $this->quote->getReservedOrderId());
+    }
+
+    public function reservedOrderIdDataProvider()
+    {
+        return [
+            'id_already_in_use' => [true, 100002],
+            'id_not_in_use' => [false, 1000001]
+        ];
+    }
 }
diff --git a/app/code/Magento/Quote/Test/Unit/Model/ResourceModel/QuoteTest.php b/app/code/Magento/Quote/Test/Unit/Model/ResourceModel/QuoteTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..15c58073c2e26a4921f771e6c4097fafc9275c91
--- /dev/null
+++ b/app/code/Magento/Quote/Test/Unit/Model/ResourceModel/QuoteTest.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Quote\Test\Unit\Model\ResourceModel;
+
+class QuoteTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Quote\Model\ResourceModel\Quote
+     */
+    private $model;
+
+    /**
+     * @var \Magento\Framework\App\ResourceConnection
+     */
+    private $resourceMock;
+
+    /**
+     * @var \Magento\Framework\DB\Adapter\Pdo\Mysql
+     */
+    private $adapterMock;
+
+    /**
+     * @var \Magento\Framework\DB\Select
+     */
+    private $selectMock;
+
+    protected function setUp()
+    {
+        $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+        $this->selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->selectMock->expects($this->any())->method('from')->will($this->returnSelf());
+        $this->selectMock->expects($this->any())->method('where');
+
+        $this->adapterMock = $this->getMockBuilder(\Magento\Framework\DB\Adapter\Pdo\Mysql::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->adapterMock->expects($this->any())->method('select')->will($this->returnValue($this->selectMock));
+
+        $this->resourceMock = $this->getMockBuilder(\Magento\Framework\App\ResourceConnection::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->resourceMock->expects(
+            $this->any()
+        )->method(
+            'getConnection'
+        )->will(
+            $this->returnValue($this->adapterMock)
+        );
+
+        $this->model = $objectManagerHelper->getObject(
+            \Magento\Quote\Model\ResourceModel\Quote::class,
+            [
+                'resource' => $this->resourceMock
+            ]
+        );
+    }
+
+    /**
+     * Unit test to verify if isOrderIncrementIdUsed method works with different types increment ids
+     *
+     * @param array $value
+     * @dataProvider isOrderIncrementIdUsedDataProvider
+     */
+    public function testIsOrderIncrementIdUsed($value)
+    {
+        $expectedBind = [':increment_id' => $value];
+        $this->adapterMock->expects($this->once())->method('fetchOne')->with($this->selectMock, $expectedBind);
+        $this->model->isOrderIncrementIdUsed($value);
+    }
+
+    /**
+     * @return array
+     */
+    public function isOrderIncrementIdUsedDataProvider()
+    {
+        return [[100000001], ['10000000001'], ['M10000000001']];
+    }
+}
diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js b/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js
index 1805dcd2f004ec91e5d3d1a96d2b0086e4b69e8c..917dc62f9f49b148d58ad62c671eb6fbeeff8beb 100644
--- a/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js
+++ b/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js
@@ -294,15 +294,20 @@ define([
         /**
          * Handler which is invoked prior to the start of a file upload.
          *
-         * @param {Event} e - Event obejct.
+         * @param {Event} e - Event object.
          * @param {Object} data - File data that will be uploaded.
          */
         onBeforeFileUpload: function (e, data) {
             var file     = data.files[0],
-                allowed  = this.isFileAllowed(file);
+                allowed  = this.isFileAllowed(file),
+                target   = $(e.target);
 
             if (allowed.passed) {
-                $(e.target).fileupload('process', data).done(function () {
+                target.on('fileuploadsend', function (event, postData) {
+                    postData.data.set('param_name', this.paramName);
+                }.bind(data));
+
+                target.fileupload('process', data).done(function () {
                     data.submit();
                 });
             } else {
diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js b/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js
index be312c71f1fb20a1a2140765d598d8567bfaf648..b640b131aaf6fcb52ca883da80de65ab0cd75dd3 100644
--- a/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js
+++ b/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js
@@ -161,7 +161,6 @@ define([
                 defaultPlaceholder: $t('Select...'),
                 lotPlaceholders: $t('Selected')
             },
-            hoverElIndex: null,
             separator: 'optgroup',
             listens: {
                 listVisible: 'cleanHoveredElement',
@@ -295,7 +294,6 @@ define([
             this._super();
             this.observe([
                 'listVisible',
-                'hoverElIndex',
                 'placeholder',
                 'multiselectFocus',
                 'options',
@@ -539,7 +537,7 @@ define([
         },
 
         /**
-         * Clean hoverElIndex variable
+         * Clean hoveredElement variable
          *
          * @returns {Object} Chainable
          */
diff --git a/app/code/Magento/Ui/view/base/web/js/lib/core/collection.js b/app/code/Magento/Ui/view/base/web/js/lib/core/collection.js
index 49133721369c85dba954788626875d1a13c26a1e..493b8c78f0cdfbf56f43c8775ab2fcd0edf5ff64 100644
--- a/app/code/Magento/Ui/view/base/web/js/lib/core/collection.js
+++ b/app/code/Magento/Ui/view/base/web/js/lib/core/collection.js
@@ -268,6 +268,14 @@ define([
 
             _.each(grouped, this.updateRegion, this);
 
+            _.each(this.regions, function (items) {
+                var hasObsoleteComponents = items().length && !_.intersection(_elems, items()).length;
+
+                if (hasObsoleteComponents) {
+                    items.removeAll();
+                }
+            });
+
             this.elems(_elems);
 
             return this;
diff --git a/app/code/Magento/User/Block/User/Edit.php b/app/code/Magento/User/Block/User/Edit.php
index f6c5b484861de36850d848e0eba2382d9688dade..116acd132a8487dbe56d933f307c40e62327bf6e 100644
--- a/app/code/Magento/User/Block/User/Edit.php
+++ b/app/code/Magento/User/Block/User/Edit.php
@@ -50,7 +50,7 @@ class Edit extends \Magento\Backend\Block\Widget\Form\Container
         $this->buttonList->update('save', 'label', __('Save User'));
         $this->buttonList->remove('delete');
 
-        $objId = $this->getRequest()->getParam($this->_objectId);
+        $objId = (int)$this->getRequest()->getParam($this->_objectId);
 
         if (!empty($objId)) {
             $this->addButton(
@@ -58,12 +58,9 @@ class Edit extends \Magento\Backend\Block\Widget\Form\Container
                 [
                     'label' => __('Delete User'),
                     'class' => 'delete',
-                    'onclick' => sprintf(
-                        'deleteConfirm("%s", "%s", %s)',
-                        __('Are you sure you want to do this?'),
-                        $this->getUrl('adminhtml/*/delete'),
-                        json_encode(['data' => ['user_id' => $objId]])
-                    ),
+                    'data_attribute' => [
+                        'role' => 'delete-user'
+                    ]
                 ]
             );
 
@@ -79,6 +76,44 @@ class Edit extends \Magento\Backend\Block\Widget\Form\Container
         }
     }
 
+    /**
+     * Returns message that is displayed for admin when he deletes user from the system.
+     * To see this message admin must do the following:
+     * - open user's account for editing;
+     * - type current user's password in the "Current User Identity Verification" field
+     * - click "Delete User" at top left part of the page;
+     *
+     * @return \Magento\Framework\Phrase
+     */
+    public function getDeleteMessage()
+    {
+        return __('Are you sure you want to do this?');
+    }
+
+    /**
+     * Returns the URL that is used for user deletion.
+     * The following Action is executed if admin navigates to returned url
+     * Magento\User\Controller\Adminhtml\User\Delete
+     *
+     * @return string
+     */
+    public function getDeleteUrl()
+    {
+        return $this->getUrl('adminhtml/*/delete');
+    }
+
+    /**
+     * This method is used to get the ID of the user who's account the Admin is editing.
+     * It can be used to determine the reason Admin opens the page:
+     * to create a new user account OR to edit the previously created user account
+     *
+     * @return int
+     */
+    public function getObjectId()
+    {
+        return (int)$this->getRequest()->getParam($this->_objectId);
+    }
+
     /**
      * @return \Magento\Framework\Phrase
      */
diff --git a/app/code/Magento/User/Controller/Adminhtml/User/Delete.php b/app/code/Magento/User/Controller/Adminhtml/User/Delete.php
index d892c8533a29716b1206ba8ee8dbeaccfc3defce..3ff336eeecff87361e79f260f30f0b77cd2c1a03 100644
--- a/app/code/Magento/User/Controller/Adminhtml/User/Delete.php
+++ b/app/code/Magento/User/Controller/Adminhtml/User/Delete.php
@@ -6,6 +6,9 @@
  */
 namespace Magento\User\Controller\Adminhtml\User;
 
+use Magento\User\Block\User\Edit\Tab\Main as UserEdit;
+use Magento\Framework\Exception\AuthenticationException;
+
 class Delete extends \Magento\User\Controller\Adminhtml\User
 {
     /**
@@ -13,8 +16,10 @@ class Delete extends \Magento\User\Controller\Adminhtml\User
      */
     public function execute()
     {
+        /** @var \Magento\User\Model\User */
         $currentUser = $this->_objectManager->get(\Magento\Backend\Model\Auth\Session::class)->getUser();
         $userId = (int)$this->getRequest()->getPost('user_id');
+
         if ($userId) {
             if ($currentUser->getId() == $userId) {
                 $this->messageManager->addError(__('You cannot delete your own account.'));
@@ -22,6 +27,11 @@ class Delete extends \Magento\User\Controller\Adminhtml\User
                 return;
             }
             try {
+                $currentUserPassword = (string)$this->getRequest()->getPost(UserEdit::CURRENT_USER_PASSWORD_FIELD);
+                if (empty($currentUserPassword)) {
+                    throw new AuthenticationException(__('You have entered an invalid password for current user.'));
+                }
+                $currentUser->performIdentityCheck($currentUserPassword);
                 /** @var \Magento\User\Model\User $model */
                 $model = $this->_userFactory->create();
                 $model->setId($userId);
diff --git a/app/code/Magento/User/Test/Unit/Controller/Adminhtml/User/DeleteTest.php b/app/code/Magento/User/Test/Unit/Controller/Adminhtml/User/DeleteTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b88b28f0016964288bca46f793f0f5adb349dd39
--- /dev/null
+++ b/app/code/Magento/User/Test/Unit/Controller/Adminhtml/User/DeleteTest.php
@@ -0,0 +1,215 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\User\Test\Unit\Controller\Adminhtml\User;
+
+use Magento\Backend\Model\Auth\Session;
+use Magento\Framework\Exception\AuthenticationException;
+
+/**
+ * Test class for \Magento\User\Controller\Adminhtml\User\Delete testing
+ */
+class DeleteTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\User\Controller\Adminhtml\User\Delete
+     */
+    private $controller;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\RequestInterface
+     */
+    private $requestMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\ResponseInterface
+     */
+    private $responseMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|Session
+     */
+    private $authSessionMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\ObjectManagerInterface
+     */
+    private $objectManagerMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\User\Model\UserFactory
+     */
+    private $userFactoryMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\User\Model\User
+     */
+    private $userMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Message\ManagerInterface
+     */
+    private $messageManagerMock;
+
+    /**
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->objectManagerMock = $this->getMockBuilder(\Magento\Framework\ObjectManager\ObjectManager::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['get', 'create'])
+            ->getMock();
+
+        $this->responseMock = $this->getMockBuilder(\Magento\Framework\App\ResponseInterface::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['setRedirect'])
+            ->getMockForAbstractClass();
+
+        $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['getPost'])
+            ->getMockForAbstractClass();
+
+        $this->authSessionMock = $this->getMockBuilder(Session::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['getUser'])
+            ->getMock();
+
+        $this->userMock = $this->getMockBuilder(\Magento\User\Model\User::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['getId', 'performIdentityCheck', 'delete'])
+            ->getMock();
+
+        $this->userFactoryMock = $this->getMockBuilder(\Magento\User\Model\UserFactory::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+
+        $this->messageManagerMock = $this->getMockBuilder(\Magento\Framework\Message\ManagerInterface::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+
+        $this->controller = $objectManager->getObject(
+            \Magento\User\Controller\Adminhtml\User\Delete::class,
+            [
+                'request'        => $this->requestMock,
+                'response'       => $this->responseMock,
+                'objectManager'  => $this->objectManagerMock,
+                'messageManager' => $this->messageManagerMock,
+                'userFactory'  => $this->userFactoryMock,
+            ]
+        );
+    }
+
+    /**
+     * Test method \Magento\User\Controller\Adminhtml\User\Delete::execute
+     *
+     * @param string $currentUserPassword
+     * @param int    $userId
+     * @param int    $currentUserId
+     * @param string $resultMethod
+     *
+     * @dataProvider executeDataProvider
+     * @return void
+     *
+     */
+    public function testExecute($currentUserPassword, $userId, $currentUserId, $resultMethod)
+    {
+        $currentUserMock = $this->userMock;
+        $this->authSessionMock->expects($this->any())->method('getUser')->will($this->returnValue($currentUserMock));
+
+        $currentUserMock->expects($this->any())->method('getId')->willReturn($currentUserId);
+
+        $this->objectManagerMock
+            ->expects($this->any())
+            ->method('get')
+            ->with(Session::class)
+            ->willReturn($this->authSessionMock);
+
+        $this->requestMock->expects($this->any())
+            ->method('getPost')
+            ->willReturnMap([
+                ['user_id', $userId],
+                [\Magento\User\Block\User\Edit\Tab\Main::CURRENT_USER_PASSWORD_FIELD, $currentUserPassword],
+            ]);
+
+        $userMock = clone $currentUserMock;
+
+        $this->userFactoryMock->expects($this->any())->method('create')->will($this->returnValue($userMock));
+        $this->responseMock->expects($this->any())->method('setRedirect')->willReturnSelf();
+        $this->userMock->expects($this->any())->method('delete')->willReturnSelf();
+        $this->messageManagerMock->expects($this->once())->method($resultMethod);
+
+        $this->controller->execute();
+    }
+
+    /**
+     * @return void
+     */
+    public function testEmptyPasswordThrowsException()
+    {
+        try {
+            $currentUserId = 1;
+            $userId = 2;
+
+            $currentUserMock = $this->userMock;
+            $this->authSessionMock->expects($this->any())
+                ->method('getUser')
+                ->will($this->returnValue($currentUserMock));
+
+            $currentUserMock->expects($this->any())->method('getId')->willReturn($currentUserId);
+
+            $this->objectManagerMock
+                ->expects($this->any())
+                ->method('get')
+                ->with(Session::class)
+                ->willReturn($this->authSessionMock);
+
+            $this->requestMock->expects($this->any())
+                ->method('getPost')
+                ->willReturnMap([
+                    ['user_id', $userId],
+                    [\Magento\User\Block\User\Edit\Tab\Main::CURRENT_USER_PASSWORD_FIELD, ''],
+                ]);
+
+            $this->controller->execute();
+        } catch (AuthenticationException $e) {
+            $this->assertEquals($e->getMessage(), 'You have entered an invalid password for current user.');
+        }
+    }
+
+    /**
+     * Data Provider for execute method
+     *
+     * @return array
+     */
+    public function executeDataProvider()
+    {
+        return [
+            [
+                'currentUserPassword' => '123123q',
+                'userId'              => 1,
+                'currentUserId'       => 2,
+                'resultMethod'        => 'addSuccess',
+            ],
+            [
+                'currentUserPassword' => '123123q',
+                'userId'              => 0,
+                'currentUserId'       => 2,
+                'resultMethod'        => 'addError',
+            ],
+            [
+                'currentUserPassword' => '123123q',
+                'userId'              => 1,
+                'currentUserId'       => 1,
+                'resultMethod'        => 'addError',
+            ],
+        ];
+    }
+}
diff --git a/app/code/Magento/User/view/adminhtml/requirejs-config.js b/app/code/Magento/User/view/adminhtml/requirejs-config.js
index 0424073c4d3db45d39394a95a99b9c697c88367d..44a5b331689bb6573c97da7f1d724e26bbea13ae 100644
--- a/app/code/Magento/User/view/adminhtml/requirejs-config.js
+++ b/app/code/Magento/User/view/adminhtml/requirejs-config.js
@@ -6,7 +6,8 @@
 var config = {
     map: {
         '*': {
-            rolesTree: 'Magento_User/js/roles-tree'
+            rolesTree: 'Magento_User/js/roles-tree',
+            deleteUserAccount: 'Magento_User/js/delete-user-account'
         }
     } 
-};
\ No newline at end of file
+};
diff --git a/app/code/Magento/User/view/adminhtml/templates/user/roles_grid_js.phtml b/app/code/Magento/User/view/adminhtml/templates/user/roles_grid_js.phtml
index bac0dd0b3f869bd33ad5d7e12886f47daded00c2..40287595b937b5426c439e0c688adbf286b36d4e 100644
--- a/app/code/Magento/User/view/adminhtml/templates/user/roles_grid_js.phtml
+++ b/app/code/Magento/User/view/adminhtml/templates/user/roles_grid_js.phtml
@@ -71,3 +71,18 @@ require([
 
 });
 </script>
+
+<?php $editBlock = $block->getLayout()->getBlock('adminhtml.user.edit'); ?>
+<?php if (is_object($editBlock)): ?>
+    <script type="text/x-magento-init">
+        {
+            "[data-role=delete-user]" : {
+                "deleteUserAccount" : {
+                    "message": "<?php echo $editBlock->escapeHtml($editBlock->getDeleteMessage()) ?>",
+                    "url": "<?php /* @noEscape */ echo $editBlock->getDeleteUrl(); ?>",
+                    "objId": "<?php echo $editBlock->escapeHtml($editBlock->getObjectId()) ?>"
+                }
+            }
+        }
+    </script>
+<?php endif; ?>
diff --git a/app/code/Magento/User/view/adminhtml/web/js/delete-user-account.js b/app/code/Magento/User/view/adminhtml/web/js/delete-user-account.js
new file mode 100644
index 0000000000000000000000000000000000000000..b326c7aeb20d06953baf406ecf339d40f5be8bc4
--- /dev/null
+++ b/app/code/Magento/User/view/adminhtml/web/js/delete-user-account.js
@@ -0,0 +1,28 @@
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define([
+    'jquery'
+], function ($) {
+    'use strict';
+
+    var postData;
+
+    return function (params, elem) {
+
+        elem.on('click', function () {
+
+            postData = {
+                'data': {
+                    'user_id': params.objId,
+                    'current_password': $('[name="current_password"]').val()
+                }
+            };
+
+            if ($.validator.validateElement($('[name="current_password"]'))) {
+                window.deleteConfirm(params.message, params.url, postData);
+            }
+        });
+    };
+});
diff --git a/app/code/Magento/Vault/Model/Method/Vault.php b/app/code/Magento/Vault/Model/Method/Vault.php
index 41a2d6b0e26efcd1c6745f5d5fbc2842ae6c8513..ca6fe06f91eef8ce52e5f0c5b0cdbd7f439f5710 100644
--- a/app/code/Magento/Vault/Model/Method/Vault.php
+++ b/app/code/Magento/Vault/Model/Method/Vault.php
@@ -5,17 +5,16 @@
  */
 namespace Magento\Vault\Model\Method;
 
-use Magento\Framework\DataObject;
 use Magento\Framework\Event\ManagerInterface;
 use Magento\Framework\ObjectManagerInterface;
 use Magento\Payment\Gateway\Command;
-use Magento\Sales\Api\Data\OrderPaymentExtensionInterfaceFactory;
 use Magento\Payment\Gateway\Config\ValueHandlerPoolInterface;
 use Magento\Payment\Gateway\ConfigFactoryInterface;
 use Magento\Payment\Gateway\ConfigInterface;
 use Magento\Payment\Model\InfoInterface;
 use Magento\Payment\Model\MethodInterface;
 use Magento\Payment\Observer\AbstractDataAssignObserver;
+use Magento\Sales\Api\Data\OrderPaymentExtensionInterfaceFactory;
 use Magento\Sales\Api\Data\OrderPaymentInterface;
 use Magento\Sales\Model\Order\Payment;
 use Magento\Vault\Api\Data\PaymentTokenInterface;
@@ -275,7 +274,12 @@ final class Vault implements VaultPaymentInterface
      */
     public function canUseInternal()
     {
-        return $this->getVaultProvider()->canUseInternal();
+        $isInternalAllowed = $this->getConfiguredValue('can_use_internal');
+        // if config has't been specified for Vault, need to check payment provider option
+        if ($isInternalAllowed === null) {
+            return $this->getVaultProvider()->canUseInternal();
+        }
+        return (bool) $isInternalAllowed;
     }
 
     /**
diff --git a/app/code/Magento/Vault/Model/Ui/Adminhtml/TokensConfigProvider.php b/app/code/Magento/Vault/Model/Ui/Adminhtml/TokensConfigProvider.php
index 98e7728f732fe51bcea79e555c5333a9cbd86684..f3a2cbfa78739d0ee748b5e38a01176ae6ed7e67 100644
--- a/app/code/Magento/Vault/Model/Ui/Adminhtml/TokensConfigProvider.php
+++ b/app/code/Magento/Vault/Model/Ui/Adminhtml/TokensConfigProvider.php
@@ -221,9 +221,11 @@ final class TokensConfigProvider
      */
     private function getPaymentTokenEntityId()
     {
-        return $this->getPaymentTokenManagement()
-            ->getByPaymentId($this->getOrderPaymentEntityId())
-            ->getEntityId();
+        $paymentToken = $this->getPaymentTokenManagement()->getByPaymentId($this->getOrderPaymentEntityId());
+        if ($paymentToken === null) {
+            throw new NoSuchEntityException(__('No available payment tokens for specified order payment.'));
+        }
+        return $paymentToken->getEntityId();
     }
 
     /**
diff --git a/app/code/Magento/Vault/Test/Unit/Model/Method/VaultTest.php b/app/code/Magento/Vault/Test/Unit/Model/Method/VaultTest.php
index 8bded498dab765a442ced658ba2562db81ca5b7e..ade93c9367858eafb1cfdf64035d2d4f9354e8a0 100644
--- a/app/code/Magento/Vault/Test/Unit/Model/Method/VaultTest.php
+++ b/app/code/Magento/Vault/Test/Unit/Model/Method/VaultTest.php
@@ -8,6 +8,8 @@ namespace Magento\Vault\Test\Unit\Model\Method;
 use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
 use Magento\Payment\Gateway\Command\CommandManagerInterface;
 use Magento\Payment\Gateway\Command\CommandManagerPoolInterface;
+use Magento\Payment\Gateway\Config\ValueHandlerInterface;
+use Magento\Payment\Gateway\Config\ValueHandlerPoolInterface;
 use Magento\Payment\Gateway\ConfigInterface;
 use Magento\Payment\Model\InfoInterface;
 use Magento\Payment\Model\MethodInterface;
@@ -19,6 +21,7 @@ use Magento\Vault\Api\Data\PaymentTokenInterface;
 use Magento\Vault\Api\PaymentTokenManagementInterface;
 use Magento\Vault\Model\Method\Vault;
 use Magento\Vault\Model\VaultPaymentInterface;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
 
 /**
  * Class VaultTest
@@ -31,9 +34,15 @@ class VaultTest extends \PHPUnit_Framework_TestCase
      */
     private $objectManager;
 
+    /**
+     * @var MethodInterface|MockObject
+     */
+    private $vaultProvider;
+
     public function setUp()
     {
         $this->objectManager = new ObjectManager($this);
+        $this->vaultProvider = $this->getMock(MethodInterface::class);
     }
 
     /**
@@ -137,8 +146,6 @@ class VaultTest extends \PHPUnit_Framework_TestCase
         $commandManagerPool = $this->getMock(CommandManagerPoolInterface::class);
         $commandManager = $this->getMock(CommandManagerInterface::class);
 
-        $vaultProvider = $this->getMock(MethodInterface::class);
-
         $tokenManagement = $this->getMock(PaymentTokenManagementInterface::class);
         $token = $this->getMock(PaymentTokenInterface::class);
 
@@ -161,7 +168,7 @@ class VaultTest extends \PHPUnit_Framework_TestCase
             ->method('setVaultPaymentToken')
             ->with($token);
 
-        $vaultProvider->expects(static::atLeastOnce())
+        $this->vaultProvider->expects(static::atLeastOnce())
             ->method('getCode')
             ->willReturn($vaultProviderCode);
         $commandManagerPool->expects(static::once())
@@ -188,7 +195,7 @@ class VaultTest extends \PHPUnit_Framework_TestCase
             [
                 'tokenManagement' => $tokenManagement,
                 'commandManagerPool' => $commandManagerPool,
-                'vaultProvider' => $vaultProvider
+                'vaultProvider' => $this->vaultProvider
             ]
         );
         $model->authorize($paymentModel, $amount);
@@ -235,10 +242,9 @@ class VaultTest extends \PHPUnit_Framework_TestCase
     {
         $storeId = 1;
         $quote = $this->getMockForAbstractClass(CartInterface::class);
-        $vaultProvider = $this->getMockForAbstractClass(MethodInterface::class);
         $config = $this->getMockForAbstractClass(ConfigInterface::class);
 
-        $vaultProvider->expects(static::once())
+        $this->vaultProvider->expects(static::once())
             ->method('isAvailable')
             ->with($quote)
             ->willReturn($isAvailableProvider);
@@ -255,7 +261,7 @@ class VaultTest extends \PHPUnit_Framework_TestCase
         /** @var Vault $model */
         $model = $this->objectManager->getObject(Vault::class, [
             'config' => $config,
-            'vaultProvider' => $vaultProvider
+            'vaultProvider' => $this->vaultProvider
         ]);
         $actual = $model->isAvailable($quote);
         static::assertEquals($expected, $actual);
@@ -281,11 +287,9 @@ class VaultTest extends \PHPUnit_Framework_TestCase
     public function testIsAvailableWithoutQuote()
     {
         $quote = null;
-
-        $vaultProvider = $this->getMockForAbstractClass(MethodInterface::class);
         $config = $this->getMockForAbstractClass(ConfigInterface::class);
 
-        $vaultProvider->expects(static::once())
+        $this->vaultProvider->expects(static::once())
             ->method('isAvailable')
             ->with($quote)
             ->willReturn(true);
@@ -298,8 +302,60 @@ class VaultTest extends \PHPUnit_Framework_TestCase
         /** @var Vault $model */
         $model = $this->objectManager->getObject(Vault::class, [
             'config' => $config,
-            'vaultProvider' => $vaultProvider
+            'vaultProvider' => $this->vaultProvider
         ]);
         static::assertFalse($model->isAvailable($quote));
     }
+
+    /**
+     * @covers \Magento\Vault\Model\Method\Vault::canUseInternal
+     * @param bool|null $configValue
+     * @param bool|null $paymentValue
+     * @param bool $expected
+     * @dataProvider internalUsageDataProvider
+     */
+    public function testCanUseInternal($configValue, $paymentValue, $expected)
+    {
+        $handlerPool = $this->getMock(ValueHandlerPoolInterface::class);
+        $handler = $this->getMock(ValueHandlerInterface::class);
+
+        $handlerPool->expects(static::once())
+            ->method('get')
+            ->with('can_use_internal')
+            ->willReturn($handler);
+
+        $handler->expects(static::once())
+            ->method('handle')
+            ->with(['field' => 'can_use_internal'], null)
+            ->willReturn($configValue);
+
+        $this->vaultProvider->expects(static::any())
+            ->method('canUseInternal')
+            ->willReturn($paymentValue);
+
+        /** @var Vault $model */
+        $model = $this->objectManager->getObject(Vault::class, [
+            'vaultProvider' => $this->vaultProvider,
+            'valueHandlerPool' => $handlerPool,
+        ]);
+        static::assertEquals($expected, $model->canUseInternal());
+    }
+
+    /**
+     * Get list of variations for testing canUseInternal method
+     * @return array
+     */
+    public function internalUsageDataProvider()
+    {
+        return [
+            ['configValue' => true, 'paymentValue' => true, 'expected' => true],
+            ['configValue' => true, 'paymentValue' => null, 'expected' => true],
+            ['configValue' => true, 'paymentValue' => false, 'expected' => true],
+            ['configValue' => false, 'paymentValue' => true, 'expected' => false],
+            ['configValue' => false, 'paymentValue' => false, 'expected' => false],
+            ['configValue' => null, 'paymentValue' => true, 'expected' => true],
+            ['configValue' => null, 'paymentValue' => false, 'expected' => false],
+            ['configValue' => null, 'paymentValue' => null, 'expected' => false],
+        ];
+    }
 }
diff --git a/app/code/Magento/Vault/Test/Unit/Model/Ui/Adminhtml/TokensConfigProviderTest.php b/app/code/Magento/Vault/Test/Unit/Model/Ui/Adminhtml/TokensConfigProviderTest.php
index 38948b004eebc358ce82eddf8bf2af88e1685c8c..bbac491386c44a231a1cc650a2ba3acfca791282 100644
--- a/app/code/Magento/Vault/Test/Unit/Model/Ui/Adminhtml/TokensConfigProviderTest.php
+++ b/app/code/Magento/Vault/Test/Unit/Model/Ui/Adminhtml/TokensConfigProviderTest.php
@@ -13,6 +13,7 @@ use Magento\Framework\Api\SearchCriteriaBuilder;
 use Magento\Framework\Exception\InputException;
 use Magento\Framework\Exception\NoSuchEntityException;
 use Magento\Framework\Intl\DateTimeFactory;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
 use Magento\Framework\TestFramework\Unit\Matcher\MethodInvokedAtIndex;
 use Magento\Payment\Helper\Data;
 use Magento\Sales\Api\Data\OrderInterface;
@@ -29,7 +30,6 @@ use Magento\Vault\Model\Ui\TokenUiComponentInterface;
 use Magento\Vault\Model\Ui\TokenUiComponentProviderInterface;
 use Magento\Vault\Model\VaultPaymentInterface;
 use PHPUnit_Framework_MockObject_MockObject as MockObject;
-use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
 
 /**
  * Class TokensConfigProviderTest
@@ -104,11 +104,21 @@ class TokensConfigProviderTest extends \PHPUnit_Framework_TestCase
      */
     private $orderRepository;
 
+    /**
+     * @var TokenUiComponentProviderInterface|MockObject
+     */
+    private $tokenComponentProvider;
+
     /**
      * @var ObjectManager
      */
     private $objectManager;
 
+    /**
+     * @var TokensConfigProvider
+     */
+    private $configProvider;
+
     protected function setUp()
     {
         $this->paymentTokenRepository = $this->getMockBuilder(PaymentTokenRepositoryInterface::class)
@@ -138,6 +148,38 @@ class TokensConfigProviderTest extends \PHPUnit_Framework_TestCase
         $this->vaultPayment = $this->getMockForAbstractClass(VaultPaymentInterface::class);
         
         $this->objectManager = new ObjectManager($this);
+
+        $this->initStoreMock();
+
+        $this->tokenComponentProvider = $this->getMock(TokenUiComponentProviderInterface::class);
+
+        $this->configProvider = new TokensConfigProvider(
+            $this->session,
+            $this->paymentTokenRepository,
+            $this->filterBuilder,
+            $this->searchCriteriaBuilder,
+            $this->storeManager,
+            $this->dateTimeFactory,
+            [
+                self::VAULT_PROVIDER_CODE => $this->tokenComponentProvider
+            ]
+        );
+
+        $this->objectManager->setBackwardCompatibleProperty(
+            $this->configProvider,
+            'paymentDataHelper',
+            $this->paymentDataHelper
+        );
+        $this->objectManager->setBackwardCompatibleProperty(
+            $this->configProvider,
+            'paymentTokenManagement',
+            $this->paymentTokenManagement
+        );
+        $this->objectManager->setBackwardCompatibleProperty(
+            $this->configProvider,
+            'orderRepository',
+            $this->orderRepository
+        );
     }
 
     /**
@@ -147,8 +189,6 @@ class TokensConfigProviderTest extends \PHPUnit_Framework_TestCase
     {
         $customerId = 1;
 
-        $this->initStoreMock();
-
         $this->session->expects(static::once())
             ->method('getCustomerId')
             ->willReturn($customerId);
@@ -170,7 +210,7 @@ class TokensConfigProviderTest extends \PHPUnit_Framework_TestCase
         $token = $this->getMockBuilder(PaymentTokenInterface::class)
             ->getMockForAbstractClass();
 
-        list($tokenUiComponent, $tokenUiComponentProvider) = $this->getTokenUiComponentProvider($token);
+        $tokenUiComponent = $this->getTokenUiComponentProvider($token);
 
         $searchCriteria = $this->getSearchCriteria($customerId, self::ENTITY_ID, self::VAULT_PROVIDER_CODE);
 
@@ -197,25 +237,7 @@ class TokensConfigProviderTest extends \PHPUnit_Framework_TestCase
             ->method('getItems')
             ->willReturn([$token]);
 
-        $configProvider = new TokensConfigProvider(
-            $this->session,
-            $this->paymentTokenRepository,
-            $this->filterBuilder,
-            $this->searchCriteriaBuilder,
-            $this->storeManager,
-            $this->dateTimeFactory,
-            [
-                self::VAULT_PROVIDER_CODE => $tokenUiComponentProvider
-            ]
-        );
-
-        $this->objectManager->setBackwardCompatibleProperty(
-            $configProvider,
-            'paymentDataHelper',
-            $this->paymentDataHelper
-        );
-
-        static::assertEquals([$tokenUiComponent], $configProvider->getTokensComponents(self::VAULT_PAYMENT_CODE));
+        static::assertEquals([$tokenUiComponent], $this->configProvider->getTokensComponents(self::VAULT_PAYMENT_CODE));
     }
 
     /**
@@ -263,7 +285,7 @@ class TokensConfigProviderTest extends \PHPUnit_Framework_TestCase
             ->method('getEntityId')
             ->willReturn(self::ENTITY_ID);
 
-        list($tokenUiComponent, $tokenUiComponentProvider) = $this->getTokenUiComponentProvider($token);
+        $tokenUiComponent = $this->getTokenUiComponentProvider($token);
 
         $searchCriteria = $this->getSearchCriteria($customerId, self::ENTITY_ID, self::VAULT_PROVIDER_CODE);
 
@@ -290,35 +312,7 @@ class TokensConfigProviderTest extends \PHPUnit_Framework_TestCase
             ->method('getItems')
             ->willReturn([$token]);
 
-        $configProvider = new TokensConfigProvider(
-            $this->session,
-            $this->paymentTokenRepository,
-            $this->filterBuilder,
-            $this->searchCriteriaBuilder,
-            $this->storeManager,
-            $this->dateTimeFactory,
-            [
-                self::VAULT_PROVIDER_CODE => $tokenUiComponentProvider
-            ]
-        );
-
-        $this->objectManager->setBackwardCompatibleProperty(
-            $configProvider,
-            'paymentDataHelper',
-            $this->paymentDataHelper
-        );
-        $this->objectManager->setBackwardCompatibleProperty(
-            $configProvider,
-            'paymentTokenManagement',
-            $this->paymentTokenManagement
-        );
-        $this->objectManager->setBackwardCompatibleProperty(
-            $configProvider,
-            'orderRepository',
-            $this->orderRepository
-        );
-
-        static::assertEquals([$tokenUiComponent], $configProvider->getTokensComponents(self::VAULT_PAYMENT_CODE));
+        static::assertEquals([$tokenUiComponent], $this->configProvider->getTokensComponents(self::VAULT_PAYMENT_CODE));
     }
 
     /**
@@ -330,8 +324,6 @@ class TokensConfigProviderTest extends \PHPUnit_Framework_TestCase
     {
         $customerId = null;
 
-        $this->initStoreMock();
-
         $this->session->expects(static::once())
             ->method('getCustomerId')
             ->willReturn($customerId);
@@ -366,35 +358,7 @@ class TokensConfigProviderTest extends \PHPUnit_Framework_TestCase
         $this->searchCriteriaBuilder->expects(self::never())
             ->method('addFilters');
 
-        $configProvider = new TokensConfigProvider(
-            $this->session,
-            $this->paymentTokenRepository,
-            $this->filterBuilder,
-            $this->searchCriteriaBuilder,
-            $this->storeManager,
-            $this->dateTimeFactory,
-            [
-                self::VAULT_PROVIDER_CODE => $this->getMock(TokenUiComponentProviderInterface::class)
-            ]
-        );
-
-        $this->objectManager->setBackwardCompatibleProperty(
-            $configProvider,
-            'paymentDataHelper',
-            $this->paymentDataHelper
-        );
-        $this->objectManager->setBackwardCompatibleProperty(
-            $configProvider,
-            'paymentTokenManagement',
-            $this->paymentTokenManagement
-        );
-        $this->objectManager->setBackwardCompatibleProperty(
-            $configProvider,
-            'orderRepository',
-            $this->orderRepository
-        );
-
-        static::assertEmpty($configProvider->getTokensComponents(self::VAULT_PAYMENT_CODE));
+        static::assertEmpty($this->configProvider->getTokensComponents(self::VAULT_PAYMENT_CODE));
     }
 
     /**
@@ -453,18 +417,66 @@ class TokensConfigProviderTest extends \PHPUnit_Framework_TestCase
         static::assertEmpty($configProvider->getTokensComponents(self::VAULT_PAYMENT_CODE));
     }
 
+    /**
+     * @covers \Magento\Vault\Model\Ui\Adminhtml\TokensConfigProvider::getTokensComponents
+     */
+    public function testGetTokensComponentsForGuestCustomerWithoutStoredTokens()
+    {
+        $this->session->expects(static::once())
+            ->method('getCustomerId')
+            ->willReturn(null);
+
+        $this->paymentDataHelper->expects(static::once())
+            ->method('getMethodInstance')
+            ->with(self::VAULT_PAYMENT_CODE)
+            ->willReturn($this->vaultPayment);
+
+        $this->vaultPayment->expects(static::once())
+            ->method('isActive')
+            ->with(self::STORE_ID)
+            ->willReturn(true);
+        $this->vaultPayment->expects(static::once())
+            ->method('getProviderCode')
+            ->willReturn(self::VAULT_PROVIDER_CODE);
+
+        $this->session->expects(static::once())
+            ->method('getReordered')
+            ->willReturn(self::ORDER_ID);
+        $this->orderRepository->expects(static::once())
+            ->method('get')
+            ->with(self::ORDER_ID)
+            ->willReturn($this->getOrderMock());
+
+        $this->paymentTokenManagement->expects(static::once())
+            ->method('getByPaymentId')
+            ->with(self::ORDER_PAYMENT_ENTITY_ID)
+            ->willReturn(null);
+
+        $this->filterBuilder->expects(static::once())
+            ->method('setField')
+            ->with(PaymentTokenInterface::ENTITY_ID)
+            ->willReturnSelf();
+        $this->filterBuilder->expects(static::never())
+            ->method('setValue');
+
+        $this->searchCriteriaBuilder->expects(static::never())
+            ->method('addFilters');
+
+        static::assertEmpty($this->configProvider->getTokensComponents(self::VAULT_PAYMENT_CODE));
+    }
+
     /**
      * Create mock object for store
      */
     private function initStoreMock()
     {
         $this->store = $this->getMock(StoreInterface::class);
-        $this->store->expects(static::once())
+        $this->store->expects(static::any())
             ->method('getId')
             ->willReturn(self::STORE_ID);
 
         $this->storeManager = $this->getMock(StoreManagerInterface::class);
-        $this->storeManager->expects(static::once())
+        $this->storeManager->expects(static::any())
             ->method('getStore')
             ->with(null)
             ->willReturn($this->store);
@@ -476,39 +488,37 @@ class TokensConfigProviderTest extends \PHPUnit_Framework_TestCase
      */
     private function getOrderMock()
     {
-        /** @var OrderInterface|MockObject $orderMock */
-        $orderMock = $this->getMockBuilder(OrderInterface::class)
+        /** @var OrderInterface|MockObject $order */
+        $order = $this->getMockBuilder(OrderInterface::class)
             ->getMockForAbstractClass();
-        /** @var OrderPaymentInterface|MockObject $orderPaymentMock */
-        $orderPaymentMock = $this->getMockBuilder(OrderPaymentInterface::class)
+        /** @var OrderPaymentInterface|MockObject $orderPayment */
+        $orderPayment = $this->getMockBuilder(OrderPaymentInterface::class)
             ->getMockForAbstractClass();
 
-        $orderMock->expects(static::once())
+        $order->expects(static::once())
             ->method('getPayment')
-            ->willReturn($orderPaymentMock);
-        $orderPaymentMock->expects(static::once())
+            ->willReturn($orderPayment);
+        $orderPayment->expects(static::once())
             ->method('getEntityId')
             ->willReturn(self::ORDER_PAYMENT_ENTITY_ID);
 
-        return $orderMock;
+        return $order;
     }
 
     /**
      * Get mock for token ui component provider
      * @param PaymentTokenInterface $token
-     * @return array
+     * @return TokenUiComponentInterface|MockObject
      */
     private function getTokenUiComponentProvider($token)
     {
         $tokenUiComponent = $this->getMock(TokenUiComponentInterface::class);
-
-        $tokenUiComponentProvider = $this->getMock(TokenUiComponentProviderInterface::class);
-        $tokenUiComponentProvider->expects(static::once())
+        $this->tokenComponentProvider->expects(static::once())
             ->method('getComponentForToken')
             ->with($token)
             ->willReturn($tokenUiComponent);
 
-        return [$tokenUiComponent, $tokenUiComponentProvider];
+        return $tokenUiComponent;
     }
 
     /**
diff --git a/app/code/Magento/Vault/view/frontend/web/js/view/payment/vault.js b/app/code/Magento/Vault/view/frontend/web/js/view/payment/vault.js
index 05d56e305f23eea9473c5c3da2d0a130ca2c42a5..3015755191d37d3159158a9505a5b3c9bf5c7bf8 100644
--- a/app/code/Magento/Vault/view/frontend/web/js/view/payment/vault.js
+++ b/app/code/Magento/Vault/view/frontend/web/js/view/payment/vault.js
@@ -4,25 +4,32 @@
  */
 /*browser:true*/
 /*global define*/
-define(
-    [
-        'underscore',
-        'uiComponent',
-        'Magento_Checkout/js/model/payment/renderer-list'
-    ],
-    function (
-        _,
-        Component,
-        rendererList
-    ) {
-        'use strict';
+define([
+    'underscore',
+    'uiComponent',
+    'Magento_Checkout/js/model/payment/renderer-list',
+    'uiLayout',
+    'uiRegistry'
+], function (_, Component, rendererList, layout, registry) {
+    'use strict';
 
+    var vaultGroupName = 'vaultGroup';
+
+    layout([{
+        name: vaultGroupName,
+        component: 'Magento_Checkout/js/model/payment/method-group',
+        alias: 'vault',
+        sortOrder: 10
+    }]);
+
+    registry.get(vaultGroupName, function (vaultGroup) {
         _.each(window.checkoutConfig.payment.vault, function (config, index) {
             rendererList.push(
                 {
                     type: index,
                     config: config.config,
                     component: config.component,
+                    group: vaultGroup,
 
                     /**
                      * Custom payment method types comparator
@@ -37,10 +44,10 @@ define(
                 }
             );
         });
+    });
 
-        /**
-         * Add view logic here if needed
-         */
-        return Component.extend({});
-    }
-);
+    /**
+     * Add view logic here if needed
+     */
+    return Component.extend({});
+});
diff --git a/app/code/Magento/Wishlist/Controller/Index/Cart.php b/app/code/Magento/Wishlist/Controller/Index/Cart.php
index f15e89d16c9b4f9bba2adbe2a23621417e255f1a..a907abcd1c56c829dedaddbd065fff3cc1fede08 100644
--- a/app/code/Magento/Wishlist/Controller/Index/Cart.php
+++ b/app/code/Magento/Wishlist/Controller/Index/Cart.php
@@ -113,6 +113,7 @@ class Cart extends \Magento\Wishlist\Controller\AbstractIndex
      * @return \Magento\Framework\Controller\ResultInterface
      * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      * @SuppressWarnings(PHPMD.NPathComplexity)
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
      */
     public function execute()
     {
@@ -137,6 +138,10 @@ class Cart extends \Magento\Wishlist\Controller\AbstractIndex
 
         // Set qty
         $qty = $this->getRequest()->getParam('qty');
+        $postQty = $this->getRequest()->getPostValue('qty');
+        if ($postQty !== null && $qty !== $postQty) {
+            $qty = $postQty;
+        }
         if (is_array($qty)) {
             if (isset($qty[$itemId])) {
                 $qty = $qty[$itemId];
diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php
index e1a7cd448569f05060d9995ee5d02de41630f680..743fc39e4b43d7819af97fc97c84efb9f3f38013 100644
--- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php
+++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php
@@ -159,7 +159,7 @@ class CartTest extends \PHPUnit_Framework_TestCase
 
         $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class)
             ->disableOriginalConstructor()
-            ->setMethods(['getParams', 'getParam', 'isAjax'])
+            ->setMethods(['getParams', 'getParam', 'isAjax', 'getPostValue'])
             ->getMockForAbstractClass();
 
         $this->redirectMock = $this->getMockBuilder(\Magento\Framework\App\Response\RedirectInterface::class)
@@ -916,4 +916,176 @@ class CartTest extends \PHPUnit_Framework_TestCase
 
         $this->assertSame($this->resultRedirectMock, $this->model->execute());
     }
+
+    /**
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function testExecuteWithEditQuantity()
+    {
+        $itemId = 2;
+        $wishlistId = 1;
+        $qty = 1;
+        $postQty = 2;
+        $productId = 4;
+        $indexUrl = 'index_url';
+        $configureUrl = 'configure_url';
+        $options = [5 => 'option'];
+        $params = ['item' => $itemId, 'qty' => $qty];
+
+        $this->formKeyValidator->expects($this->once())
+            ->method('validate')
+            ->with($this->requestMock)
+            ->willReturn(true);
+
+        $itemMock = $this->getMockBuilder(\Magento\Wishlist\Model\Item::class)
+            ->disableOriginalConstructor()
+            ->setMethods(
+                [
+                    'load',
+                    'getId',
+                    'getWishlistId',
+                    'setQty',
+                    'setOptions',
+                    'getBuyRequest',
+                    'mergeBuyRequest',
+                    'addToCart',
+                    'getProduct',
+                    'getProductId',
+                ]
+            )
+            ->getMock();
+
+        $this->requestMock->expects($this->at(0))
+            ->method('getParam')
+            ->with('item', null)
+            ->willReturn($itemId);
+        $this->itemFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($itemMock);
+
+        $itemMock->expects($this->once())
+            ->method('load')
+            ->with($itemId, null)
+            ->willReturnSelf();
+        $itemMock->expects($this->exactly(2))
+            ->method('getId')
+            ->willReturn($itemId);
+        $itemMock->expects($this->once())
+            ->method('getWishlistId')
+            ->willReturn($wishlistId);
+
+        $wishlistMock = $this->getMockBuilder(\Magento\Wishlist\Model\Wishlist::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->wishlistProviderMock->expects($this->once())
+            ->method('getWishlist')
+            ->with($wishlistId)
+            ->willReturn($wishlistMock);
+
+        $this->requestMock->expects($this->at(1))
+            ->method('getParam')
+            ->with('qty', null)
+            ->willReturn($qty);
+
+        $this->requestMock->expects($this->once())
+            ->method('getPostValue')
+            ->with('qty')
+            ->willReturn($postQty);
+
+        $this->quantityProcessorMock->expects($this->once())
+            ->method('process')
+            ->with($postQty)
+            ->willReturnArgument(0);
+
+        $itemMock->expects($this->once())
+            ->method('setQty')
+            ->with($postQty)
+            ->willReturnSelf();
+
+        $this->urlMock->expects($this->at(0))
+            ->method('getUrl')
+            ->with('*/*', null)
+            ->willReturn($indexUrl);
+
+        $itemMock->expects($this->once())
+            ->method('getProductId')
+            ->willReturn($productId);
+
+        $this->urlMock->expects($this->at(1))
+            ->method('getUrl')
+            ->with('*/*/configure/', ['id' => $itemId, 'product_id' => $productId])
+            ->willReturn($configureUrl);
+
+        $optionMock = $this->getMockBuilder(\Magento\Wishlist\Model\Item\Option::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->optionFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($optionMock);
+
+        $optionsMock = $this->getMockBuilder(\Magento\Wishlist\Model\ResourceModel\Item\Option\Collection::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $optionMock->expects($this->once())
+            ->method('getCollection')
+            ->willReturn($optionsMock);
+
+        $optionsMock->expects($this->once())
+            ->method('addItemFilter')
+            ->with([$itemId])
+            ->willReturnSelf();
+        $optionsMock->expects($this->once())
+            ->method('getOptionsByItem')
+            ->with($itemId)
+            ->willReturn($options);
+
+        $itemMock->expects($this->once())
+            ->method('setOptions')
+            ->with($options)
+            ->willReturnSelf();
+
+        $this->requestMock->expects($this->once())
+            ->method('getParams')
+            ->willReturn($params);
+
+        $buyRequestMock = $this->getMockBuilder(\Magento\Framework\DataObject::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $itemMock->expects($this->once())
+            ->method('getBuyRequest')
+            ->willReturn($buyRequestMock);
+
+        $this->productHelperMock->expects($this->once())
+            ->method('addParamsToBuyRequest')
+            ->with($params, ['current_config' => $buyRequestMock])
+            ->willReturn($buyRequestMock);
+
+        $itemMock->expects($this->once())
+            ->method('mergeBuyRequest')
+            ->with($buyRequestMock)
+            ->willReturnSelf();
+        $itemMock->expects($this->once())
+            ->method('addToCart')
+            ->with($this->checkoutCartMock, true)
+            ->willThrowException(new \Magento\Framework\Exception\LocalizedException(__('message')));
+
+        $this->messageManagerMock->expects($this->once())
+            ->method('addNotice')
+            ->with('message', null)
+            ->willReturnSelf();
+
+        $this->helperMock->expects($this->once())
+            ->method('calculate')
+            ->willReturnSelf();
+
+        $this->resultRedirectMock->expects($this->once())
+            ->method('setUrl')
+            ->with($configureUrl)
+            ->willReturnSelf();
+
+        $this->assertSame($this->resultRedirectMock, $this->model->execute());
+    }
 }
diff --git a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml
index dbb680f8f25806508e44ef31724899149ca2b6ce..b08816a6728eb54b79ec806084f4a4e684702a29 100644
--- a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml
+++ b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml
@@ -22,7 +22,7 @@
                        template="Magento_Catalog::product/view/addto.phtml" cacheable="false">
                     <block class="Magento\Wishlist\Block\Item\Configure" name="view.addto.wishlist.bundle" after="view.addto.requisition"
                            template="item/configure/addto/wishlist.phtml" />
-                    <block class="Magento\Catalog\Block\Product\View\Addto\Compare" name="view.addto.compare.bundle" after="view.addto.wishlist"
+                    <block class="Magento\Catalog\Block\Product\View\AddTo\Compare" name="view.addto.compare.bundle" after="view.addto.wishlist"
                            template="Magento_Catalog::product/view/addto/compare.phtml" />
                 </block>
             </block>
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less
index 7731595870f061c990acc5cc36d68980e8ba590f..453a9ce958f4d3f2716c015c99ff72a525b3838f 100644
--- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less
@@ -24,6 +24,7 @@
 & when (@media-common = true) {
     .checkout-payment-method {
         .step-title {
+            border-bottom: 0;
             margin-bottom: 0;
         }
 
@@ -39,6 +40,12 @@
                     display: block;
                 }
             }
+
+            & + .payment-method {
+                .payment-method-title {
+                    .lib-css(border-top, @checkout-payment-method-title__border);
+                }
+            }
         }
 
         .payment-method-content {
@@ -54,7 +61,6 @@
         }
 
         .payment-method-title {
-            .lib-css(border-top, @checkout-payment-method-title__border);
             .lib-css(padding, @checkout-payment-method-title__padding 0);
             margin: 0;
 
@@ -80,6 +86,14 @@
             }
         }
 
+        .payment-group {
+            & + .payment-group {
+                .step-title {
+                    margin: @indent__base 0 0;
+                }
+            }
+        }
+
         .field-select-billing,
         .billing-address-form {
             .lib-css(max-width, @checkout-billing-address-form__max-width);
diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less
index 85b2e96e6ea4add2316a572f0ce4ad16bfe073d2..a8c84ef51a92af04d403be3eb522610693a9a823 100644
--- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less
+++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less
@@ -24,6 +24,7 @@
 & when (@media-common = true) {
     .checkout-payment-method {
         .step-title {
+            border-bottom: 0;
             margin-bottom: 0;
         }
 
@@ -39,6 +40,12 @@
                     display: block;
                 }
             }
+
+            & + .payment-method {
+                .payment-method-title {
+                    .lib-css(border-top, @checkout-payment-method-title__border);
+                }
+            }
         }
 
         .payment-method-content {
@@ -54,7 +61,6 @@
         }
 
         .payment-method-title {
-            .lib-css(border-top, @checkout-payment-method-title__border);
             .lib-css(padding, @checkout-payment-method-title__padding 0);
             margin: 0;
 
@@ -80,6 +86,14 @@
             }
         }
 
+        .payment-group {
+            & + .payment-group {
+                .step-title {
+                    margin: @indent__base 0 0;
+                }
+            }
+        }
+
         .field-select-billing,
         .billing-address-form {
             .lib-css(max-width, @checkout-billing-address-form__max-width);
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/Annotation/ApiDataFixture.php b/dev/tests/api-functional/framework/Magento/TestFramework/Annotation/ApiDataFixture.php
index 5eeb7ddb61fa05657b08dda4711e82938e8778ce..0ad53eeeb90d9dab3a8877624429efefe314aefd 100644
--- a/dev/tests/api-functional/framework/Magento/TestFramework/Annotation/ApiDataFixture.php
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/Annotation/ApiDataFixture.php
@@ -51,6 +51,7 @@ class ApiDataFixture
      */
     public function startTest(\PHPUnit_Framework_TestCase $test)
     {
+        \Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize();
         /** Apply method level fixtures if thy are available, apply class level fixtures otherwise */
         $this->_applyFixtures($this->_getFixtures('method', $test) ?: $this->_getFixtures('class', $test));
     }
@@ -61,6 +62,9 @@ class ApiDataFixture
     public function endTest()
     {
         $this->_revertFixtures();
+        /** @var $objectManager \Magento\TestFramework\ObjectManager */
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $objectManager->get(\Magento\Eav\Model\Entity\AttributeCache::class)->clear();
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderWithPayPalBraintreeVaultBackendTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderWithPayPalBraintreeVaultBackendTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6fde39412d1fe66a987b12cf5cb29e09d81327fe
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderWithPayPalBraintreeVaultBackendTest.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Braintree\Test\TestCase;
+
+use Magento\Mtf\TestCase\Scenario;
+
+/**
+ * Preconditions:
+ * 1. Configure shipping method.
+ * 2. Configure payment method.
+ * 3. Create products.
+ * 4. Create and setup customer.
+ *
+ * Steps:
+ * 1. Log in Storefront.
+ * 2. Add products to the Shopping Cart.
+ * 3. In 'Estimate Shipping and Tax' section specify destination using values from Test Data.
+ * 4. Click the 'Proceed to Checkout' button.
+ * 5. Fill shipping information.
+ * 6. Select shipping method.
+ * 8. Select payment method
+ * 9. Verify order total on review step.
+ * 10. Click 'Continue to PayPal' button.
+ * 11. Click 'Proceed purchase' in popup.
+ * 12. Log in Admin panel.
+ * 13. Open placed order.
+ * 14. Click 'Reorder' button.
+ * 15. Select stored Braintree PayPal token.
+ * 16. Click 'Submit Order'.
+ * 17. Perform assertions.
+ *
+ * @group Braintree
+ * @ZephyrId MAGETWO-59259
+ */
+class CreateOrderWithPayPalBraintreeVaultBackendTest extends Scenario
+{
+    /* tags */
+    const MVP = 'yes';
+
+    const TEST_TYPE = '3rd_party_test';
+
+    const SEVERITY = 'S0';
+    /* end tags */
+
+    /**
+     * Runs test scenario
+     * @return void
+     */
+    public function test()
+    {
+        $this->executeScenario();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderWithPayPalBraintreeVaultBackendTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderWithPayPalBraintreeVaultBackendTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..03e0ba330fa3b74e2a33c2983655ced95cf3dbfe
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderWithPayPalBraintreeVaultBackendTest.xml
@@ -0,0 +1,32 @@
+<?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\Braintree\Test\TestCase\CreateOrderWithPayPalBraintreeVaultBackendTest" summary="Checkout with PayPal Braintree Vault token from Admin">
+        <variation name="CreateOrderWithPayPalBraintreeVaultBackendTestVariation1" summary="Checkout with PayPal Braintree Vault token from Admin" ticketId="MAGETWO-59259">
+            <data name="tag" xsi:type="string">est_type:3rd_party_test, severity:S0</data>
+            <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data>
+            <data name="customer/dataset" xsi:type="string">default</data>
+            <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data>
+            <data name="checkoutMethod" xsi:type="string">login</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">braintree_paypal</data>
+            <data name="vault/method" xsi:type="string">braintree_paypal_vault</data>
+            <data name="status" xsi:type="string">Processing</data>
+            <data name="configData" xsi:type="string">braintree, braintree_paypal, braintree_paypal_use_vault, braintree_paypal_skip_order_review</data>
+            <data name="prices" xsi:type="array">
+                <item name="grandTotal" xsi:type="string">15.00</item>
+            </data>
+            <constraint name="Magento\Sales\Test\Constraint\AssertOrderSuccessCreateMessage" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertAuthorizationInCommentsHistory" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGrid" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateVaultOrderBackendTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateVaultOrderBackendTest.xml
index db6cd3572eaa2acec5ded94997b1951c744e6652..c9b26df050cfc9cf9ef4913a4f538459cee1923f 100644
--- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateVaultOrderBackendTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateVaultOrderBackendTest.xml
@@ -19,6 +19,7 @@
                 <item name="grandTotal" xsi:type="string">15.00</item>
             </data>
             <data name="payment/method" xsi:type="string">braintree</data>
+            <data name="vault/method" xsi:type="string">braintree_cc_vault</data>
             <data name="creditCardClass" xsi:type="string">credit_card_braintree</data>
             <data name="creditCard/dataset" xsi:type="string">visa_braintree</data>
             <data name="creditCardSave" xsi:type="string">Yes</data>
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml
index 5a99c4a89a313392cdd596891712b1d2d4bbaec3..ad4d5cc06e92e260aed4c90e6f534f2540d25034 100644
--- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml
@@ -19,6 +19,7 @@
                 <item name="grandTotal" xsi:type="string">15.00</item>
             </data>
             <data name="payment/method" xsi:type="string">braintree</data>
+            <data name="vault/method" xsi:type="string">braintree_cc_vault</data>
             <data name="creditCardClass" xsi:type="string">credit_card_braintree</data>
             <data name="creditCard/dataset" xsi:type="string">visa_braintree</data>
             <data name="configData" xsi:type="string">braintree, braintree_use_vault</data>
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/testcase.xml
index 34f4be6493838598b9872225997736da38b07ff7..495f455c43a72f4d61029a07a8633fc09744c2f0 100644
--- a/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/testcase.xml
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/testcase.xml
@@ -158,4 +158,21 @@
         <step name="changeOrderStatusToPaymentReview" module="Magento_Braintree" next="denyPayment" />
         <step name="denyPayment" module="Magento_Braintree" />
     </scenario>
+    <scenario name="CreateOrderWithPayPalBraintreeVaultBackendTest" 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="estimateShippingAndTax" />
+        <step name="estimateShippingAndTax" module="Magento_Checkout" next="clickProceedToCheckout" />
+        <step name="clickProceedToCheckout" 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="placeOrderWithPaypal" />
+        <step name="placeOrderWithPaypal" module="Magento_Braintree" next="openOrder"/>
+        <step name="openOrder" module="Magento_Sales" next="reorder" />
+        <step name="reorder" module="Magento_Sales" next="useVaultPaymentToken" />
+        <step name="useVaultPaymentToken" module="Magento_Vault" next="submitOrder" />
+        <step name="submitOrder" module="Magento_Sales" />
+    </scenario>
 </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 ecd68593b08cc252e67a144ccd2a9610ac88f22d..e1cbc1a1d8ba2dba7f3be971b3f1b456f6e7d02a 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml
@@ -1233,5 +1233,35 @@
             <field name="url_key" xsi:type="string">overnight-duffle</field>
         </dataset>
 
+        <dataset name="simple_with_weight_10_for_salesrule">
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="name" xsi:type="string">Simple Product %isolation%</field>
+            <field name="sku" xsi:type="string">sku_simple_product_%isolation%</field>
+            <field name="product_has_weight" xsi:type="string">This item has weight</field>
+            <field name="weight" xsi:type="string">10</field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="qty" xsi:type="string">25</item>
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="price" xsi:type="array">
+                <item name="value" xsi:type="string">560</item>
+            </field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="url_key" xsi:type="string">simple-product-%isolation%</field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">simple_order_default</item>
+            </field>
+        </dataset>
+
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php
index 697733fd3c33d8856f5d775452aca8ad977e77e9..fac0f811be2616675e85e3f34927731f13ea16b1 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php
@@ -99,6 +99,13 @@ class Cart extends Block
      */
     protected $preloaderSpinner = '#preloaderSpinner';
 
+    /**
+     * Cart item class name.
+     *
+     * @var string
+     */
+    protected $cartItemClass = \Magento\Checkout\Test\Block\Cart\CartItem::class;
+
     /**
      * Wait for PayPal page is loaded.
      *
@@ -129,7 +136,7 @@ class Cart extends Block
                 Locator::SELECTOR_XPATH
             );
             $cartItem = $this->blockFactory->create(
-                '\\' . get_class($this) . '\CartItem',
+                $this->cartItemClass,
                 ['element' => $cartItemBlock]
             );
         }
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php
index a3eda5ea1b3c5a3d6b5be217df906ca69b67f742..d29bad980faca881468ae1cf3a58523e13f7ad83 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php
@@ -13,5 +13,13 @@ use Magento\Mtf\Block\Form;
  */
 class Shipping extends Form
 {
-    //
+    /**
+     * Returns form's required elements
+     *
+     * @return \Magento\Mtf\Client\ElementInterface[]
+     */
+    public function getRequiredFields()
+    {
+        return $this->_rootElement->getElements("div .field._required");
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertShippingAddressJsValidationMessagesIsAbsent.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertShippingAddressJsValidationMessagesIsAbsent.php
new file mode 100644
index 0000000000000000000000000000000000000000..f4f46a1c2b7c2577a0f61882f9d707397b1c1a20
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertShippingAddressJsValidationMessagesIsAbsent.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Checkout\Test\Constraint;
+
+use Magento\Checkout\Test\Page\CheckoutOnepage;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Class AssertShippingAddressJsValidationMessagesIsAbsent
+ * Assert js validation messages are absent for required fields.
+ */
+class AssertShippingAddressJsValidationMessagesIsAbsent extends AbstractConstraint
+{
+    /**
+     * Assert js validation messages are absent for required fields.
+     *
+     * @param CheckoutOnepage $checkoutOnepage
+     * @return void
+     */
+    public function processAssert(CheckoutOnepage $checkoutOnepage)
+    {
+        $requiredFields = $checkoutOnepage->getShippingBlock()->getRequiredFields();
+
+        /** @var \Magento\Mtf\Client\ElementInterface $field */
+        foreach ($requiredFields as $field) {
+            $errorContainer = $field->find("div .field-error");
+            \PHPUnit_Framework_Assert::assertFalse(
+                $errorContainer->isVisible(),
+                'Js validation error messages must be absent for required fields after checkout start.'
+            );
+        }
+    }
+
+    /**
+     * Returns string representation of successful assertion
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Js validation messages are absent for required fields.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..5361ee6e3c127bafc03e53cd717ac067688f826a
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Checkout\Test\TestCase;
+
+use Magento\Mtf\TestCase\Scenario;
+
+/**
+ * Steps:
+ * 1. Go to Frontend as guest.
+ * 2. Add simple product to shopping cart
+ * 3. Go to shopping cart page
+ * 4. Proceed to checkout
+ * 5. Perform assertions.
+ *
+ * @group One_Page_Checkout
+ * @ZephyrId MAGETWO-59697
+ */
+class OnePageCheckoutJsValidationTest extends Scenario
+{
+    /**
+     * Runs one page checkout js validation test.
+     *
+     * @return void
+     */
+    public function test()
+    {
+        $this->executeScenario();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e930ff29882ceed4e8f99947a6a6ef4b4acc1c7a
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\Checkout\Test\TestCase\OnePageCheckoutJsValidationTest" summary="JS validation verification for Checkout flow" ticketId="MAGETWO-59697">
+        <variation name="OnePageCheckoutJsValidationTestVariation1" summary="JS validation is not applied for empty required checkout fields if customer did not fill them">
+            <data name="products/0" xsi:type="string">catalogProductSimple::default</data>
+            <data name="checkoutMethod" xsi:type="string">guest</data>
+            <constraint name="Magento\Checkout\Test\Constraint\AssertShippingAddressJsValidationMessagesIsAbsent" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml
index a26a2cead49b07a094e550db1207e36d53269b15..24eb96c0a9347741384ffd6718bf349eeb452c85 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml
@@ -22,4 +22,10 @@
         <step name="placeOrder" module="Magento_Checkout" next="createCustomerAccount" />
         <step name="createCustomerAccount" module="Magento_Checkout" />
     </scenario>
+    <scenario name="OnePageCheckoutJsValidationTest" firstStep="setupConfiguration">
+        <step name="setupConfiguration" module="Magento_Config" next="createProducts" />
+        <step name="createProducts" module="Magento_Catalog" next="addProductsToTheCart" />
+        <step name="addProductsToTheCart" module="Magento_Checkout" next="ProceedToCheckout" />
+        <step name="ProceedToCheckout" module="Magento_Checkout" />
+    </scenario>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateVaultOrderBackendTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateVaultOrderBackendTest.xml
index 38666c36a2ba4e53641f45616060353ca5e5e22c..ca26ad42a020c80ab0540c21a2928b8a1874cae7 100644
--- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateVaultOrderBackendTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateVaultOrderBackendTest.xml
@@ -19,6 +19,7 @@
                 <item name="grandTotal" xsi:type="string">15.00</item>
             </data>
             <data name="payment/method" xsi:type="string">payflowpro</data>
+            <data name="vault/method" xsi:type="string">payflowpro_cc_vault</data>
             <data name="creditCardClass" xsi:type="string">credit_card_admin</data>
             <data name="creditCard/dataset" xsi:type="string">visa_default</data>
             <data name="creditCardSave" xsi:type="string">Yes</data>
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml
index c33abb1dbdd2263fded6dbbfb0f683848a3bdd3f..b1da43e473bc5d78d4bfaf0fbcbb718dac6acd3e 100644
--- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml
@@ -19,6 +19,7 @@
                 <item name="grandTotal" xsi:type="string">15.00</item>
             </data>
             <data name="payment/method" xsi:type="string">payflowpro</data>
+            <data name="vault/method" xsi:type="string">payflowpro_cc_vault</data>
             <data name="creditCardClass" xsi:type="string">credit_card</data>
             <data name="creditCard/dataset" xsi:type="string">visa_default</data>
             <data name="configData" xsi:type="string">payflowpro, payflowpro_use_vault</data>
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/Curl.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/Curl.php
index 5ab10a0e26f79fcded0b42c77562b077cf0b5412..310f52f75e2cf124e07ab1d7d4bf431e48759e8d 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/Curl.php
@@ -70,6 +70,10 @@ class Curl extends Conditions implements SalesRuleInterface
             'type' => \Magento\SalesRule\Model\Rule\Condition\Address::class,
             'attribute' => 'postcode',
         ],
+        'Total Weight' => [
+            'type' => \Magento\SalesRule\Model\Rule\Condition\Address::class,
+            'attribute' => 'weight',
+        ],
         'Category' => [
             'type' => \Magento\SalesRule\Model\Rule\Condition\Product::class,
             'attribute' => 'category_ids',
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml
index 010b9d3233d163f6ec35ed4291bebbe352bbe9c4..13b68aca6c6eb7867286019b3a9609b3b93db2a8 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml
@@ -279,5 +279,24 @@
             <field name="stop_rules_processing" xsi:type="string">No</field>
             <field name="simple_free_shipping" xsi:type="string">No</field>
         </dataset>
+        <dataset name="rule_with_freeshipping_by_weight">
+            <field name="name" xsi:type="string">Cart price rule with free shipping by weight</field>
+            <field name="is_active" xsi:type="string">Yes</field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="string">Main Website</item>
+            </field>
+            <field name="customer_group_ids" xsi:type="array">
+                <item name="0" xsi:type="string">NOT LOGGED IN</item>
+            </field>
+            <field name="coupon_type" xsi:type="string">No Coupon</field>
+            <field name="sort_order" xsi:type="string">1</field>
+            <field name="is_rss" xsi:type="string">Yes</field>
+            <field name="conditions_serialized" xsi:type="string">[Total Weight|is|1]</field>
+            <field name="simple_action" xsi:type="string">Percent of product price discount</field>
+            <field name="discount_amount" xsi:type="string">0</field>
+            <field name="apply_to_shipping" xsi:type="string">No</field>
+            <field name="stop_rules_processing" xsi:type="string">No</field>
+            <field name="simple_free_shipping" xsi:type="string">For matching items only</field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ShoppingCartWithFreeShippingTest.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ShoppingCartWithFreeShippingTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..11e510759fdcc5aa4c9368e61c3f5373d32dd9bb
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ShoppingCartWithFreeShippingTest.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\SalesRule\Test\TestCase;
+
+/**
+ * Precondition:
+ * 1. Cart Price Rule was created.
+ *
+ * Steps:
+ * 1. Go to storefront
+ * 2. Add product to shopping cart
+ * 3. Go to shopping cart page
+ * 4. Perform asserts.
+ *
+ * @group Shopping_Cart_Price_Rules
+ * @ZephyrId MAGETWO-59665
+ */
+class ShoppingCartWithFreeShippingTest extends \Magento\Mtf\TestCase\Injectable
+{
+    /**
+     * @var \Magento\Mtf\TestStep\TestStepFactory
+     */
+    private $testStepFactory;
+
+    /**
+     * Inject data
+     *
+     * @param \Magento\Mtf\TestStep\TestStepFactory $testStepFactory
+     * @return void
+     */
+    public function __inject(
+        \Magento\Mtf\TestStep\TestStepFactory $testStepFactory
+    ) {
+        $this->testStepFactory = $testStepFactory;
+    }
+
+    /**
+     * Test sales rule with free shipping applied by product weight
+     *
+     * @param \Magento\SalesRule\Test\Fixture\SalesRule $salesRule
+     * @param \Magento\Catalog\Test\Fixture\CatalogProductSimple $product
+     * @param \Magento\Checkout\Test\Fixture\Cart $cart
+     * @return void
+     */
+    public function testRuleWithFreeShippingByWeight(
+        \Magento\SalesRule\Test\Fixture\SalesRule $salesRule,
+        \Magento\Catalog\Test\Fixture\CatalogProductSimple $product,
+        \Magento\Checkout\Test\Fixture\Cart $cart
+    ) {
+        $salesRule->persist();
+        $product->persist();
+
+        $this->testStepFactory->create(
+            \Magento\Checkout\Test\TestStep\AddProductsToTheCartStep::class,
+            ['products' => [$product]]
+        )->run();
+
+        $this->testStepFactory->create(
+            \Magento\Checkout\Test\TestStep\EstimateShippingAndTaxStep::class,
+            ['products' => [$product], 'cart' => $cart]
+        )->run();
+    }
+
+    /**
+     * Clear data after test.
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        $this->testStepFactory->create(\Magento\SalesRule\Test\TestStep\DeleteAllSalesRuleStep::class)->run();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ShoppingCartWithFreeShippingTest.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ShoppingCartWithFreeShippingTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7391d2281f8094b059cfaf9d26115c371d9498b0
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ShoppingCartWithFreeShippingTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\SalesRule\Test\TestCase\ShoppingCartWithFreeShippingTest" summary="Shopping Cart With Freeshipping" ticketId="MAGETWO-59665">
+        <variation name="ShoppingCartWithFreeShippingTestVariation1">
+            <data name="salesRule/dataset" xsi:type="string">rule_with_freeshipping_by_weight</data>
+            <data name="product/dataset" xsi:type="string">default</data>
+            <data name="cart/data/subtotal" xsi:type="string">560.00</data>
+            <data name="cart/data/shipping_amount" xsi:type="string">0.00</data>
+            <data name="cart/data/grand_total" xsi:type="string">560.00</data>
+        </variation>
+        <variation name="ShoppingCartWithFreeShippingTestVariation2">
+            <data name="salesRule/dataset" xsi:type="string">rule_with_freeshipping_by_weight</data>
+            <data name="product/dataset" xsi:type="string">simple_with_weight_10_for_salesrule</data>
+            <data name="cart/data/subtotal" xsi:type="string">560.00</data>
+            <data name="cart/data/shipping_amount" xsi:type="string">5.00</data>
+            <data name="cart/data/grand_total" xsi:type="string">565.00</data>
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Repository/User.xml b/dev/tests/functional/tests/app/Magento/User/Test/Repository/User.xml
index 25b812bf77665d09877835e676fc5d11fdd1434a..dbb7a4aeb53bb667bf22e99e0198d1b0e3cab25c 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
@@ -41,5 +41,9 @@
             <field name="current_password" xsi:type="string">%current_password%</field>
             <field name="is_active" xsi:type="string">Active</field>
         </dataset>
+
+        <dataset name="system_admin">
+            <field name="current_password" xsi:type="string">123123q</field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteAdminUserEntityTest.php b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteAdminUserEntityTest.php
index 57de56c7f56f7397282e1863ec43a3f42c6a9ec2..67ede3855e7a77b7da397a42c4de161289387b8f 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteAdminUserEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteAdminUserEntityTest.php
@@ -101,11 +101,13 @@ class DeleteAdminUserEntityTest extends Injectable
      *
      * @param User $user
      * @param string $isDefaultUser
+     * @param User $systemAdmin
      * @return void
      */
     public function testDeleteAdminUserEntity(
         User $user,
-        $isDefaultUser
+        $isDefaultUser,
+        User $systemAdmin = null
     ) {
         $filter = [
             'username' => $user->getUsername(),
@@ -118,6 +120,7 @@ class DeleteAdminUserEntityTest extends Injectable
         }
         $this->userIndex->open();
         $this->userIndex->getUserGrid()->searchAndOpen($filter);
+        $this->userEdit->getUserForm()->fill($systemAdmin);
         $this->userEdit->getPageActions()->delete();
         $this->userEdit->getModalBlock()->acceptAlert();
     }
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteAdminUserEntityTest.xml b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteAdminUserEntityTest.xml
index 782c3243eaa6be76578a9fc9f8b670fb6920c4da..fd10c53dfd53393dfcf122888a4d7b9e1003228a 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteAdminUserEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteAdminUserEntityTest.xml
@@ -9,11 +9,13 @@
     <testCase name="Magento\User\Test\TestCase\DeleteAdminUserEntityTest" summary="Delete Admin User" ticketId="MAGETWO-23416">
         <variation name="DeleteAdminUserEntityTestVariation1">
             <data name="isDefaultUser" xsi:type="string">0</data>
+            <data name="systemAdmin/dataset" xsi:type="string">system_admin</data>
             <constraint name="Magento\User\Test\Constraint\AssertImpossibleDeleteYourOwnAccount" />
             <constraint name="Magento\User\Test\Constraint\AssertUserInGrid" />
         </variation>
         <variation name="DeleteAdminUserEntityTestVariation2">
             <data name="isDefaultUser" xsi:type="string">1</data>
+            <data name="systemAdmin/dataset" xsi:type="string">system_admin</data>
             <constraint name="Magento\User\Test\Constraint\AssertUserSuccessDeleteMessage" />
             <constraint name="Magento\User\Test\Constraint\AssertUserNotInGrid" />
         </variation>
diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/UseVaultPaymentTokenStep.php b/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/UseVaultPaymentTokenStep.php
index ad693923955d4f439340970eb07ebb7c14789574..066dc7786d892619e84272c69b655cfd8a74f140 100644
--- a/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/UseVaultPaymentTokenStep.php
+++ b/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/UseVaultPaymentTokenStep.php
@@ -17,20 +17,20 @@ class UseVaultPaymentTokenStep implements TestStepInterface
      * @var OrderCreateIndex
      */
     private $orderCreatePage;
-    
+
     /**
      * @var array
      */
-    private $payment;
+    private $vault;
 
     /**
      * @param OrderCreateIndex $orderCreateIndex
-     * @param array $payment
+     * @param array $vault
      */
-    public function __construct(OrderCreateIndex $orderCreateIndex, array $payment)
+    public function __construct(OrderCreateIndex $orderCreateIndex, array $vault)
     {
         $this->orderCreatePage = $orderCreateIndex;
-        $this->payment = $payment;
+        $this->vault = $vault;
     }
 
     /**
@@ -39,8 +39,7 @@ class UseVaultPaymentTokenStep implements TestStepInterface
     public function run()
     {
         $block = $this->orderCreatePage->getCreateBlock();
-        $this->payment['method'] .= '_cc_vault';
-        $block->selectPaymentMethod($this->payment);
-        $block->selectVaultToken('token_switcher_' . $this->payment['method']);
+        $block->selectPaymentMethod($this->vault);
+        $block->selectVaultToken('token_switcher_' . $this->vault['method']);
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Customer/Wishlist.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Customer/Wishlist.php
index 47f787da38b04264372015a52449f984820490e5..bda0780f553006bddc3f0ce164cb4f6f824ee75d 100644
--- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Customer/Wishlist.php
+++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Block/Customer/Wishlist.php
@@ -99,6 +99,7 @@ class Wishlist extends Block
     public function clickUpdateWishlist()
     {
         $this->waitFormToLoad();
+        $this->_rootElement->hover();
         $this->_rootElement->find($this->updateButton)->click();
     }
 
diff --git a/dev/tests/integration/testsuite/Magento/Braintree/Model/Ui/Adminhtml/PayPal/TokenUiComponentProviderTest.php b/dev/tests/integration/testsuite/Magento/Braintree/Model/Ui/Adminhtml/PayPal/TokenUiComponentProviderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e79f4ad361e36d315e7bc30846325bbe97445d1e
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Braintree/Model/Ui/Adminhtml/PayPal/TokenUiComponentProviderTest.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Braintree\Model\Ui\Adminhtml\PayPal;
+
+use Magento\Braintree\Model\Ui\Adminhtml\PayPal\TokenUiComponentProvider;
+use Magento\Braintree\Model\Ui\PayPal\ConfigProvider;
+use Magento\Framework\ObjectManagerInterface;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\Vault\Model\PaymentTokenManagement;
+use Magento\Vault\Model\Ui\TokenUiComponentProviderInterface;
+
+/**
+ * Contains tests for PayPal token Ui component provider
+ */
+class TokenUiComponentProviderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var ObjectManagerInterface
+     */
+    private $objectManager;
+
+    /**
+     * @var TokenUiComponentProvider
+     */
+    private $tokenComponentProvider;
+
+    protected function setUp()
+    {
+        $this->objectManager = Bootstrap::getObjectManager();
+        $this->tokenComponentProvider = $this->objectManager->get(TokenUiComponentProvider::class);
+    }
+
+    /**
+     * @covers \Magento\Braintree\Model\Ui\Adminhtml\PayPal\TokenUiComponentProvider::getComponentForToken
+     * @magentoDataFixture Magento/Braintree/_files/paypal_vault_token.php
+     * @magentoAppArea adminhtml
+     */
+    public function testGetComponentForToken()
+    {
+        $customerId = 1;
+        $token = 'mx29vk';
+        $payerEmail = 'john.doe@example.com';
+
+        /** @var PaymentTokenManagement $tokenManagement */
+        $tokenManagement = $this->objectManager->get(PaymentTokenManagement::class);
+        $paymentToken = $tokenManagement->getByGatewayToken($token, ConfigProvider::PAYPAL_CODE, $customerId);
+
+        $component = $this->tokenComponentProvider->getComponentForToken($paymentToken);
+        $config = $component->getConfig();
+
+        static::assertNotEmpty($config[TokenUiComponentProviderInterface::COMPONENT_DETAILS]);
+        static::assertNotEmpty($config[TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH]);
+        static::assertEquals(ConfigProvider::PAYPAL_VAULT_CODE, $config['code']);
+
+        $details = $config[TokenUiComponentProviderInterface::COMPONENT_DETAILS];
+        static::assertEquals($payerEmail, $details['payerEmail']);
+        static::assertNotEmpty($details['icon']);
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryTest.php
index a3e90819912f03a9413311600c7cd5cbcfddff60..49787c94038a1d9b1c3991c7f6261c0b7ef1453e 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryTest.php
@@ -293,7 +293,7 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
             ->isObjectNew(true);
 
         $repository->save($model);
-        $this->assertNull($model->getImage());
+        $this->assertEmpty($model->getImage());
     }
 
     /**
diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php
index 0afede93546f2c8ba69f8af9b64b70013b5d2c22..dc9e440b045f86ad2e85de45124ac01881d3892c 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php
@@ -227,7 +227,34 @@ class ProductTest extends \PHPUnit_Framework_TestCase
 
         $this->assertContains('""Option 2""', $exportData);
         $this->assertContains('""Option 3""', $exportData);
-        $this->assertContains('""Option 4 """"!@#$%^&*"""', $exportData);
-        $this->assertContains('text_attribute=""!@#$%^&*()_+1234567890-=|\:;"""', $exportData);
+        $this->assertContains('""Option 4 """"!@#$%^&*""', $exportData);
+        $this->assertContains('text_attribute=""!@#$%^&*()_+1234567890-=|\:;""""\'<,>.?/', $exportData);
+    }
+
+    /**
+     * Verify that "category ids" filter correctly applies to export result
+     *
+     * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_with_categories.php
+     */
+    public function testCategoryIdsFilter()
+    {
+        $this->model->setWriter(
+            $this->objectManager->create(
+                \Magento\ImportExport\Model\Export\Adapter\Csv::class
+            )
+        );
+
+        $this->model->setParameters([
+            \Magento\ImportExport\Model\Export::FILTER_ELEMENT_GROUP => [
+                'category_ids' => '2,13'
+            ]
+        ]);
+
+        $exportData = $this->model->export();
+
+        $this->assertContains('Simple Product', $exportData);
+        $this->assertContains('Simple Product Three', $exportData);
+        $this->assertNotContains('Simple Product Two', $exportData);
+        $this->assertNotContains('Simple Product Not Visible On Storefront', $exportData);
     }
 }
diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_categories.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_categories.php
new file mode 100644
index 0000000000000000000000000000000000000000..e65ff00bcffcabd1e2fdeae3810876178e0d06aa
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_categories.php
@@ -0,0 +1,9 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+\Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize();
+
+require dirname(dirname(__DIR__)) . '/Catalog/_files/categories.php';
diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_shipping_method_and_items_categories.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_shipping_method_and_items_categories.php
index 7fb35a4412bf8bbbda969b646a23eee84aac61ac..ec230f3c5126185e21d27226c65f6e09e7f125e5 100644
--- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_shipping_method_and_items_categories.php
+++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_shipping_method_and_items_categories.php
@@ -56,7 +56,7 @@ $product->setTypeId(
 )->setId(
     444
 )->setAttributeSetId(
-    5
+    4
 )->setStoreId(
     1
 )->setWebsiteIds(
diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php
index da035c8eec78f8a547defd548f5cc93b10d474a6..8f295077afe330076e265c555cae280294cdd9f6 100644
--- a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php
+++ b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php
@@ -404,4 +404,23 @@ class QuoteTest extends \PHPUnit_Framework_TestCase
             \Magento\Customer\Model\Data\Customer::WEBSITE_ID => 1
         ];
     }
+
+    /**
+     * Test to verify that reserved_order_id will be changed if it already in used
+     *
+     * @magentoDataFixture Magento/Sales/_files/order.php
+     * @magentoDataFixture Magento/Quote/_files/empty_quote.php
+     */
+    public function testReserveOrderId()
+    {
+        $objectManager = Bootstrap::getObjectManager();
+        /** @var \Magento\Quote\Model\Quote  $quote */
+        $quote = $objectManager->create(\Magento\Quote\Model\Quote::class);
+        $quote->load('reserved_order_id', 'reserved_order_id');
+        $quote->reserveOrderId();
+        $this->assertEquals('reserved_order_id', $quote->getReservedOrderId());
+        $quote->setReservedOrderId('100000001');
+        $quote->reserveOrderId();
+        $this->assertNotEquals('100000001', $quote->getReservedOrderId());
+    }
 }
diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/ResourceModel/QuoteTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/ResourceModel/QuoteTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..43ee0893b75f9cc93bdca626d87d5592eefd62aa
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Quote/Model/ResourceModel/QuoteTest.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Quote\Model\ResourceModel;
+
+/**
+ * Class QuoteTest to verify isOrderIncrementIdUsed method behaviour
+ */
+class QuoteTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Quote\Model\ResourceModel\Quote
+     */
+    private $_resourceModel;
+
+    protected function setUp()
+    {
+        $this->_resourceModel = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
+            \Magento\Quote\Model\ResourceModel\Quote::class
+        );
+    }
+
+    /**
+     * Test to verify if isOrderIncrementIdUsed method works with numeric increment ids
+     *
+     * @magentoDataFixture Magento/Sales/_files/order.php
+     */
+    public function testIsOrderIncrementIdUsedNumericIncrementId()
+    {
+        $this->assertTrue($this->_resourceModel->isOrderIncrementIdUsed('100000001'));
+    }
+
+    /**
+     * Test to verify if isOrderIncrementIdUsed method works with alphanumeric increment ids
+     *
+     * @magentoDataFixture Magento/Sales/_files/order_alphanumeric_id.php
+     */
+    public function testIsOrderIncrementIdUsedAlphanumericIncrementId()
+    {
+        $this->assertTrue($this->_resourceModel->isOrderIncrementIdUsed('M00000001'));
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/Model/Quote/Address/Total/ShippingTest.php b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Quote/Address/Total/ShippingTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..543d02e42067483a56ee1b31d084a7e02c18952f
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Quote/Address/Total/ShippingTest.php
@@ -0,0 +1,106 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\SalesRule\Model\Quote\Address\Total;
+
+class ShippingTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Quote\Api\GuestCartManagementInterface
+     */
+    private $cartManagement;
+
+    /**
+     * @var \Magento\Quote\Api\GuestCartItemRepositoryInterface
+     */
+    private $itemRepository;
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    private $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->cartManagement = $this->objectManager->get(\Magento\Quote\Api\GuestCartManagementInterface::class);
+        $this->itemRepository = $this->objectManager->get(\Magento\Quote\Api\GuestCartItemRepositoryInterface::class);
+    }
+
+    /**
+     * @magentoDataFixture Magento/SalesRule/_files/rule_free_shipping_by_product_weight.php
+     * @magentoDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testRuleByProductWeightWithFreeShipping()
+    {
+        $cartId = $this->prepareQuote(1);
+        $methods = $this->estimateShipping($cartId);
+
+        $this->assertTrue(count($methods) > 0);
+        $this->assertEquals('flatrate', $methods[0]->getMethodCode());
+        $this->assertEquals(0, $methods[0]->getAmount());
+
+    }
+
+    /**
+     * @magentoDataFixture Magento/SalesRule/_files/rule_free_shipping_by_product_weight.php
+     * @magentoDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testRuleByProductWeightWithoutFreeShipping()
+    {
+        $cartId = $this->prepareQuote(5);
+        $methods = $this->estimateShipping($cartId);
+
+        $this->assertTrue(count($methods) > 0);
+        $this->assertEquals('flatrate', $methods[0]->getMethodCode());
+        $this->assertEquals(25, $methods[0]->getAmount());
+
+    }
+
+    /**
+     * Estimate shipment for guest cart
+     *
+     * @param int $cartId
+     * @return \Magento\Quote\Api\Data\ShippingMethodInterface[]
+     */
+    private function estimateShipping($cartId)
+    {
+        $addressFactory = $this->objectManager->get(\Magento\Quote\Api\Data\AddressInterfaceFactory::class);
+        /** @var \Magento\Quote\Api\Data\AddressInterface $address */
+        $address = $addressFactory->create();
+        $address->setCountryId('US');
+        $address->setRegionId(2);
+
+        /** @var \Magento\Quote\Api\GuestShipmentEstimationInterface $estimation */
+        $estimation = $this->objectManager->get(\Magento\Quote\Api\GuestShipmentEstimationInterface::class);
+        return $estimation->estimateByExtendedAddress($cartId, $address);
+    }
+
+    /**
+     * Create guest quote with products
+     *
+     * @param int $itemQty
+     * @return int
+     */
+    private function prepareQuote($itemQty)
+    {
+        $cartId = $this->cartManagement->createEmptyCart();
+
+        /** @var \Magento\Quote\Api\Data\CartItemInterfaceFactory $cartItemFactory */
+        $cartItemFactory = $this->objectManager->get(\Magento\Quote\Api\Data\CartItemInterfaceFactory::class);
+
+        /** @var \Magento\Quote\Api\Data\CartItemInterface $cartItem */
+        $cartItem = $cartItemFactory->create();
+        $cartItem->setQuoteId($cartId);
+        $cartItem->setQty($itemQty);
+        $cartItem->setSku('simple');
+        $cartItem->setProductType(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE);
+
+        $this->itemRepository->save($cartItem);
+
+        return $cartId;
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/_files/rule_free_shipping_by_product_weight.php b/dev/tests/integration/testsuite/Magento/SalesRule/_files/rule_free_shipping_by_product_weight.php
new file mode 100644
index 0000000000000000000000000000000000000000..d59f63d2f313601b06bafdac7287501980e20b37
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/SalesRule/_files/rule_free_shipping_by_product_weight.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+require 'cart_rule_free_shipping.php';
+$row =
+    [
+        'name' => 'Free shipping if item weight <= 1',
+        'conditions' => [
+            1 =>
+                [
+                    'type' => \Magento\SalesRule\Model\Rule\Condition\Combine::class,
+                    'attribute' => null,
+                    'operator' => null,
+                    'value' => '1',
+                    'is_value_processed' => null,
+                    'aggregator' => 'all',
+                    'conditions' => [
+                        [
+                            'type' => Magento\SalesRule\Model\Rule\Condition\Address::class,
+                            'attribute' => 'weight',
+                            'operator' => '<=',
+                            'value' => '1',
+                            'is_value_processed' => false,
+                        ]
+                    ]
+                ]
+
+        ],
+        'actions' => [],
+    ];
+$salesRule->loadPost($row);
+$salesRule->save();
diff --git a/dev/tests/js/jasmine/spec_runner/tasks/jasmine.js b/dev/tests/js/jasmine/spec_runner/tasks/jasmine.js
index 5d520860f44105371984c918ddd643f1f05c1611..ccd21fafe33b9220f3203bf4fa0697ad2abc2d2f 100644
--- a/dev/tests/js/jasmine/spec_runner/tasks/jasmine.js
+++ b/dev/tests/js/jasmine/spec_runner/tasks/jasmine.js
@@ -37,6 +37,10 @@ function init(config) {
                 host: host,
                 template: render(files.template),
                 vendor: files.requireJs,
+                junit: {
+                    path: "var/log/js-unit/",
+                    consolidate: true
+                },
 
                 /**
                  * @todo rename "helpers" to "specs" (implies overriding grunt-contrib-jasmine code)
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js
index 806964352be5f23ea088d91b683400d00020c342..6fbbc63af473c36baa9f5c7fdf55d2e0fa6b907c 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/collection/item.test.js
@@ -21,38 +21,6 @@ define([
             index: ''
         });
 
-        registry.set('provName', {
-            on: function () {
-            },
-            get: function () {
-            },
-            set: function () {
-            }
-        });
-
-        describe('"initProperties" method', function () {
-            it('Check for defined ', function () {
-                expect(obj.hasOwnProperty('initProperties')).toBeDefined();
-            });
-            it('Check answer type', function () {
-                var type = typeof obj.initProperties;
-
-                expect(type).toEqual('function');
-            });
-            it('Check returned value if method called without arguments', function () {
-                expect(obj.initProperties()).toBeDefined();
-            });
-            it('Check returned value type if method called without arguments', function () {
-                var type = typeof obj.initProperties();
-
-                expect(type).toEqual('object');
-            });
-            it('Check "displayed" property', function () {
-                obj.displayed = null;
-                obj.initProperties();
-                expect(obj.displayed).toEqual([]);
-            });
-        });
         describe('"initObservable" method', function () {
             it('Check for defined ', function () {
                 expect(obj.hasOwnProperty('initObservable')).toBeDefined();
@@ -178,16 +146,23 @@ define([
                     prefix: 'magento'
                 };
 
+                obj.getPreview = jasmine.createSpy().and.callFake(function () {
+                    return [];
+                });
+
                 expect(obj.buildPreview(arg)).toBeDefined();
             });
             it('Check returned value type if method called with object argument', function () {
                 var arg = {
                         items: [],
                         prefix: 'magento'
-                    },
-                    type = typeof obj.buildPreview(arg);
+                    };
+
+                obj.getPreview = jasmine.createSpy().and.callFake(function () {
+                    return [];
+                });
 
-                expect(type).toEqual('string');
+                expect(typeof obj.buildPreview(arg)).toEqual('string');
             });
             it('Check called "this.getPreview" method with object argument', function () {
                 var arg = {
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab.test.js
index 56449c04406a08f0a8a5bc021726322ecd13bd59..10c9e5d35daeddeb16fa89b928f357b7770bdd66 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab.test.js
@@ -56,23 +56,6 @@ define([
                 expect(obj.observe).toHaveBeenCalled();
             });
         });
-        describe('"onUniqueUpdate" method', function () {
-            it('Check for defined ', function () {
-                expect(obj.hasOwnProperty('onUniqueUpdate')).toBeDefined();
-            });
-            it('Check method type', function () {
-                var type = typeof obj.onUniqueUpdate;
-
-                expect(type).toEqual('function');
-            });
-            it('Check called "this.trigger" inner onUniqueUpdate method', function () {
-                obj.trigger = jasmine.createSpy().and.callFake(function () {
-                    return obj;
-                });
-                obj.onUniqueUpdate();
-                expect(obj.trigger).toHaveBeenCalled();
-            });
-        });
         describe('"activate" method', function () {
             it('Check for defined ', function () {
                 expect(obj.hasOwnProperty('activate')).toBeDefined();
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab_group.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab_group.test.js
index 173e803b14a2151df665ebd97bd145cf374f26ee..311b023a003a85fba8f8d4a7beb89f8cb65dce04 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab_group.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/components/tab_group.test.js
@@ -23,14 +23,6 @@ define([
         });
 
         window.FORM_KEY = 'magentoFormKey';
-        registry.set('provName', {
-            on: function () {
-            },
-            get: function () {
-            },
-            set: function () {
-            }
-        });
 
         describe('"initElement" method', function () {
             it('Check for defined ', function () {
@@ -48,6 +40,8 @@ define([
                     on: function () {
                     },
                     active: function () {
+                    },
+                    activate: function () {
                     }
                 };
 
@@ -60,6 +54,8 @@ define([
                         on: function () {
                         },
                         active: function () {
+                        },
+                        activate: function () {
                         }
                     },
                     type = typeof obj.initElement(arg);
@@ -83,6 +79,8 @@ define([
                     on: function () {
                     },
                     active: function () {
+                    },
+                    activate: function () {
                     }
                 };
 
@@ -95,6 +93,8 @@ define([
                         on: function () {
                         },
                         active: function () {
+                        },
+                        activate: function () {
                         }
                     },
                     type = typeof obj.initActivation(arg);
@@ -119,6 +119,8 @@ define([
                     },
                     active: function () {
                     },
+                    activate: function () {
+                    },
                     delegate: jasmine.createSpy()
                 };
 
@@ -150,7 +152,7 @@ define([
                     return [];
                 });
                 obj.onValidate();
-                expect(obj.validate.calls.count()).toBe(3);
+                expect(obj.validate.calls.count()).toBe(1);
             });
         });
     });
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/abstract.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/abstract.test.js
index 0923d84fce5ff0e39149219a2ba951dcc1b6ebf9..7730bc72f7af6e35ffea47a4e2c6831328672dcc 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/abstract.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/abstract.test.js
@@ -43,17 +43,6 @@ define([
                 expect(model.validation).toEqual({});
             });
         });
-        describe('initProperties method', function () {
-            it('check for chainable', function () {
-                expect(model.initProperties()).toEqual(model);
-            });
-            it('check for extend', function () {
-                model.initProperties();
-                expect(model.uid).toBeDefined();
-                expect(model.noticeId).toBeDefined();
-                expect(model.inputName).toBeDefined();
-            });
-        });
         describe('setInitialValue method', function () {
             it('check for chainable', function () {
                 expect(model.setInitialValue()).toEqual(model);
@@ -78,15 +67,23 @@ define([
                 expect(model.additionalClasses).toEqual(1);
             });
             it('check for empty additional class', function () {
+                var expectedResult = {
+                    _required: model.required,
+                    _warn: model.warn,
+                    _error: model.error,
+                    _disabled: model.disabled
+                };
+
                 model.additionalClasses = '';
 
                 expect(model._setClasses()).toEqual(model);
-                expect(model.additionalClasses).toEqual('');
+                expect(model.additionalClasses).toEqual(expectedResult);
             });
             it('check for one class in additional', function () {
                 var extendObject = {
                     simple: true,
-                    required: model.required,
+                    _required: model.required,
+                    _warn: model.warn,
                     _error: model.error,
                     _disabled: model.disabled
                 };
@@ -98,7 +95,8 @@ define([
             it('check for one class with spaces in additional', function () {
                 var extendObject = {
                     simple: true,
-                    required: model.required,
+                    _required: model.required,
+                    _warn: model.warn,
                     _error: model.error,
                     _disabled: model.disabled
                 };
@@ -111,7 +109,8 @@ define([
                 var extendObject = {
                     simple: true,
                     example: true,
-                    required: model.required,
+                    _required: model.required,
+                    _warn: model.warn,
                     _error: model.error,
                     _disabled: model.disabled
                 };
@@ -124,7 +123,8 @@ define([
                 var extendObject = {
                     simple: true,
                     example: true,
-                    required: model.required,
+                    _required: model.required,
+                    _warn: model.warn,
                     _error: model.error,
                     _disabled: model.disabled
                 };
@@ -139,10 +139,8 @@ define([
                 expect(model.getInitialValue()).toEqual('');
             });
             it('check with default value', function () {
-                var expected = 1;
-
-                model.default = expected;
-                expect(model.getInitialValue()).toEqual(expected);
+                model.default = 1;
+                expect(model.getInitialValue()).toEqual('');
             });
             it('check with value', function () {
                 var expected = 1;
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js
index 632fef3d841d1becdc65ff4e8ddfdcc553a3557f..de6b83eaf2005d06c324c3b7da997b541d305522 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js
@@ -19,33 +19,5 @@ define([
             };
             model = new DateElement(params);
         });
-
-        describe('getInitialValue method', function () {
-            it('check for default', function () {
-                expect(model.getInitialValue()).toEqual('');
-            });
-            it('check with default value', function () {
-                model.default = 1;
-                expect(model.getInitialValue()).toEqual('01/01/1970');
-            });
-            it('check with value', function () {
-                model.value(1);
-                expect(model.getInitialValue()).toEqual('01/01/1970');
-            });
-            it('check with value and default', function () {
-                model.default = 1;
-                model.value(0);
-                expect(model.getInitialValue()).toEqual(0);
-            });
-        });
-        describe('initProperties method', function () {
-            it('check for chainable', function () {
-                expect(model.initProperties()).toEqual(model);
-            });
-            it('check for extend', function () {
-                model.initProperties();
-                expect(model.dateFormat).toBeDefined();
-            });
-        });
     });
 });
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/multiselect.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/multiselect.test.js
deleted file mode 100644
index 09f21f6b175ee21661cc8138ae319fc9be98bd14..0000000000000000000000000000000000000000
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/multiselect.test.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-/*eslint max-nested-callbacks: 0*/
-
-define([
-    'Magento_Ui/js/form/element/multiselect'
-], function (MultiselectElement) {
-    'use strict';
-
-    describe('Magento_Ui/js/form/element/multiselect', function () {
-        var params, model;
-
-        beforeEach(function () {
-            params = {
-                dataScope: 'multiselect'
-            };
-            model = new MultiselectElement(params);
-        });
-
-        describe('getInitialValue method', function () {
-            it('check for default', function () {
-                expect(model.getInitialValue()).toEqual(undefined);
-            });
-            it('check with default value', function () {
-                model.indexedOptions = {
-                    Select: {
-                        value: 'value'
-                    }
-                };
-                model.default = 'Select';
-                expect(model.getInitialValue()).toEqual(['value']);
-            });
-            it('check with value', function () {
-                model.indexedOptions = {
-                    Select: {
-                        value: 'value'
-                    }
-                };
-                model.value('Select');
-                expect(model.getInitialValue()).toEqual(['value']);
-            });
-        });
-    });
-});
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js
index 6ce3428a6cb35f4a15063de0ba26e3612e1605d2..db5855b0a692bb7ac0c9b75de35d228abe309016 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js
@@ -52,64 +52,6 @@ define([
             it('check for chainable', function () {
                 expect(model.initConfig({})).toEqual(model);
             });
-            it('check with empty value and caption', function () {
-                var config = {
-                    options: [{
-                        label: 'Caption',
-                        value: null
-                    }, {
-                        label: 'Some label',
-                        value: 'Some value'
-                    }],
-                    caption: 'Main caption'
-                },
-                expected = {
-                    options: [config.options[1]],
-                    caption: config.caption
-                };
-
-                expect(model.initConfig(config)).toEqual(model);
-                expect(config).toEqual(expected);
-            });
-            it('check with empty value', function () {
-                var config = {
-                        options: [{
-                            label: 'Caption',
-                            value: null
-                        }, {
-                            label: 'Some label',
-                            value: 'Some value'
-                        }]
-                    },
-                    expected = {
-                        options: [config.options[1]],
-                        caption: config.options[0].label
-                    };
-
-                expect(model.initConfig(config)).toEqual(model);
-                expect(config).toEqual(expected);
-            });
-            it('check with multiple empty value', function () {
-                var config = {
-                        options: [{
-                            label: 'Caption',
-                            value: null
-                        }, {
-                            label: 'Some label',
-                            value: 'Some value'
-                        }, {
-                            label: 'Another caption',
-                            value: null
-                        }]
-                    },
-                    expected = {
-                        options: [config.options[1]],
-                        caption: config.options[0].label
-                    };
-
-                expect(model.initConfig(config)).toEqual(model);
-                expect(config).toEqual(expected);
-            });
         });
         describe('initObservable method', function () {
             it('check for chainable', function () {
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/form.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/form.test.js
index 5a32d5c991e3e06b50647c03057a3cc19ac1239f..88203afba331333193482a79c3e061202e93a2b4 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/form.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/form.test.js
@@ -67,26 +67,26 @@ define([
                 expect(type).toEqual('object');
             });
         });
-        describe('"initProperties" method', function () {
+        describe('"initConfig" method', function () {
             it('Check for defined ', function () {
-                expect(obj.hasOwnProperty('initProperties')).toBeDefined();
+                expect(obj.hasOwnProperty('initConfig')).toBeDefined();
             });
             it('Check method type', function () {
-                var type = typeof obj.initProperties;
+                var type = typeof obj.initConfig;
 
                 expect(type).toEqual('function');
             });
             it('Check returned value if method called without arguments', function () {
-                expect(obj.initProperties()).toBeDefined();
+                expect(obj.initConfig()).toBeDefined();
             });
             it('Check returned value type if method called without arguments', function () {
-                var type = typeof obj.initProperties();
+                var type = typeof obj.initConfig();
 
                 expect(type).toEqual('object');
             });
-            it('Check this.selector property (is modify in initProperties method)', function () {
+            it('Check this.selector property (is modify in initConfig method)', function () {
                 obj.selector = null;
-                obj.initProperties();
+                obj.initConfig();
                 expect(typeof obj.selector).toEqual('string');
             });
         });
@@ -117,33 +117,6 @@ define([
 
                 expect(type).toEqual('function');
             });
-            it('Check call method "this.validate" inner save method', function () {
-                obj.validate = jasmine.createSpy();
-                obj.source.get = jasmine.createSpy().and.callFake(function () {
-                    return true;
-                });
-                obj.save();
-                expect(obj.validate).toHaveBeenCalled();
-            });
-            it('Check call method "this.source.get" inner save method', function () {
-                obj.validate = jasmine.createSpy();
-                obj.source.get = jasmine.createSpy().and.callFake(function () {
-                    return true;
-                });
-                obj.save();
-                expect(obj.source.get).toHaveBeenCalled();
-            });
-            it('Check call method "this.submit" inner save method', function () {
-                obj.validate = jasmine.createSpy();
-                obj.source.get = jasmine.createSpy().and.callFake(function () {
-                    return false;
-                });
-                obj.submit = jasmine.createSpy().and.callFake(function () {
-                    return true;
-                });
-                obj.save();
-                expect(obj.source.get).toHaveBeenCalled();
-            });
         });
         describe('"submit" method', function () {
             it('Check for defined ', function () {
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/ui-select.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/ui-select.test.js
index 6a646c7c709099b917a08df1f3f795cce262dca0..5ffa5792b0882385c26546d6fbd834f3dde68a03 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/ui-select.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/ui-select.test.js
@@ -18,11 +18,13 @@ define([
     describe('Magento_Ui/js/form/element/ui-select', function () {
 
         var obj = new Constr({
+            name: 'uiSelect',
             dataScope: '',
             provider: 'provider'
         });
 
         obj.value = ko.observableArray([]);
+        obj.cacheOptions.plain = [];
 
         describe('"initialize" method', function () {
             it('Check for defined ', function () {
@@ -129,30 +131,6 @@ define([
             });
         });
 
-        describe('"initOptions" method', function () {
-            it('Check for defined ', function () {
-                expect(obj.hasOwnProperty('initOptions')).toBeDefined();
-            });
-            it('Check answer type', function () {
-                var type = typeof obj.initOptions;
-
-                expect(type).toEqual('function');
-            });
-            it('Check returned value if method called without arguments', function () {
-                expect(obj.initOptions()).toBeDefined();
-            });
-            it('Check returned value type if method called without arguments', function () {
-                var type = typeof obj.initOptions();
-
-                expect(type).toEqual('object');
-            });
-            it('Check "this.optionsConfig.options" property', function () {
-                obj.optionsConfig.options = null;
-                obj.initOptions();
-                expect(obj.optionsConfig.options).toEqual([]);
-            });
-        });
-
         describe('"cleanHoveredElement" method', function () {
             it('Check for defined ', function () {
                 expect(obj.hasOwnProperty('cleanHoveredElement')).toBeDefined();
@@ -170,11 +148,6 @@ define([
 
                 expect(type).toEqual('object');
             });
-            it('Check changes "this.hoverElIndex" observe variable', function () {
-                obj.hoverElIndex(5);
-                obj.cleanHoveredElement();
-                expect(obj.hoverElIndex()).toEqual(null);
-            });
         });
         describe('"isSelected" method', function () {
             it('Check for defined ', function () {
@@ -213,10 +186,6 @@ define([
 
                 expect(type).toEqual('boolean');
             });
-            it('Must return false if "hoverElIndex" does not equal value', function () {
-                obj.hoverElIndex(1);
-                expect(obj.isHovered(2)).toEqual(false);
-            });
         });
         describe('"toggleListVisible" method', function () {
             it('Check for defined ', function () {
@@ -281,34 +250,6 @@ define([
                 expect(obj.value()).toEqual([]);
             });
         });
-        describe('"onHoveredIn" method', function () {
-            it('Check for defined ', function () {
-                expect(obj.hasOwnProperty('onHoveredIn')).toBeDefined();
-            });
-            it('Check answer type', function () {
-                var type = typeof obj.onHoveredIn;
-
-                expect(type).toEqual('function');
-            });
-            it('Observe variable "hoverElIndex" must have transmitted value', function () {
-                obj.onHoveredIn({}, 5);
-                expect(obj.hoverElIndex()).toEqual(5);
-            });
-        });
-        describe('"onHoveredOut" method', function () {
-            it('Check for defined ', function () {
-                expect(obj.hasOwnProperty('onHoveredOut')).toBeDefined();
-            });
-            it('Check answer type', function () {
-                var type = typeof obj.onHoveredOut;
-
-                expect(type).toEqual('function');
-            });
-            it('Observe variable "hoverElIndex" must be null', function () {
-                obj.onHoveredOut();
-                expect(obj.hoverElIndex()).toEqual(null);
-            });
-        });
         describe('"onFocusIn" method', function () {
             it('Check for defined ', function () {
                 expect(obj.hasOwnProperty('onFocusIn')).toBeDefined();
@@ -319,7 +260,7 @@ define([
                 expect(type).toEqual('function');
             });
             it('Observe variable "multiselectFocus" must be true', function () {
-                obj.onFocusIn();
+                obj.onFocusIn({}, {});
                 expect(obj.multiselectFocus()).toEqual(true);
             });
         });
@@ -351,14 +292,6 @@ define([
                 obj.enterKeyHandler();
                 expect(obj.listVisible()).toEqual(true);
             });
-            it('if list visible is true, method "toggleOptionSelected" must be called with argument', function () {
-                obj.listVisible(true);
-                obj.hoverElIndex(0);
-                obj.options(['magento']);
-                obj.toggleOptionSelected = jasmine.createSpy();
-                obj.enterKeyHandler();
-                expect(obj.toggleOptionSelected).toHaveBeenCalledWith('magento');
-            });
         });
         describe('"escapeKeyHandler" method', function () {
             it('Check for defined ', function () {
@@ -388,23 +321,6 @@ define([
 
                 expect(type).toEqual('function');
             });
-            it('If "hoverElIndex" is null - "hoverElIndex" must be 0', function () {
-                obj.hoverElIndex(null);
-                obj.pageDownKeyHandler();
-                expect(obj.hoverElIndex()).toEqual(0);
-            });
-            it('If "hoverElIndex" is number - "hoverElIndex" must be number + 1', function () {
-                obj.hoverElIndex(1);
-                obj.options(['one', 'two', 'three']);
-                obj.pageDownKeyHandler();
-                expect(obj.hoverElIndex()).toEqual(2);
-            });
-            it('If "hoverElIndex" is number and number === options length -1, "hoverElIndex" must be 0', function () {
-                obj.hoverElIndex(1);
-                obj.options(['one', 'two']);
-                obj.pageDownKeyHandler();
-                expect(obj.hoverElIndex()).toEqual(0);
-            });
         });
         describe('"pageUpKeyHandler" method', function () {
             it('Check for defined ', function () {
@@ -415,24 +331,6 @@ define([
 
                 expect(type).toEqual('function');
             });
-            it('If "hoverElIndex" is null - "hoverElIndex" must be option length -1', function () {
-                obj.hoverElIndex(null);
-                obj.options(['one', 'two']);
-                obj.pageUpKeyHandler();
-                expect(obj.hoverElIndex()).toEqual(1);
-            });
-            it('If "hoverElIndex" is 0 - "hoverElIndex" must be option length -1', function () {
-                obj.hoverElIndex(0);
-                obj.options(['one', 'two']);
-                obj.pageUpKeyHandler();
-                expect(obj.hoverElIndex()).toEqual(1);
-            });
-            it('If "hoverElIndex" is number - "hoverElIndex" must be number - 1', function () {
-                obj.hoverElIndex(2);
-                obj.options(['one', 'two']);
-                obj.pageUpKeyHandler();
-                expect(obj.hoverElIndex()).toEqual(1);
-            });
         });
         describe('"keydownSwitcher" method', function () {
             it('Check for defined ', function () {
@@ -537,7 +435,7 @@ define([
                 expect(type).toEqual('function');
             });
             it('Check returned value if selected', function () {
-                obj.cacheOptions = [{value: 'magento'}, {value: 'magento2'}];
+                obj.cacheOptions.plain = [{value: 'magento'}, {value: 'magento2'}];
                 obj.value(['magento', 'magento2']);
 
                 expect(obj.getSelected()).toEqual([{value: 'magento'}, {value: 'magento2'}]);
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/actions.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/actions.test.js
index c282660342ad1c25a7b0f35dd9d095fcaeb7604b..318e09453dc5af8f3f4d3f43e10c208c615a8b6c 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/actions.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/actions.test.js
@@ -82,19 +82,5 @@ define([
             action.hidden = false;
             expect(model.isActionVisible(action)).toBeTruthy();
         });
-
-        it('Check toggleList function', function () {
-            model.toggleList(0);
-            expect(model.opened()).toEqual(0);
-            model.toggleList(0);
-            expect(model.opened()).toBeFalsy();
-        });
-
-        it('Check closeList function', function () {
-            model.toggleList(0);
-            expect(model.opened()).toEqual(0);
-            model.closeList(0);
-            expect(model.opened()).toBeFalsy();
-        });
     });
 });
\ No newline at end of file
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/column.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/column.test.js
index b4db54bdb7b65fec6a557dd12f0d10e878277ece..ccfccdd195f0292163eab823ae5b15a61713594c 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/column.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/column.test.js
@@ -17,7 +17,8 @@ define([
                 sortable: true,
                 sorting: false,
                 headerTmpl: 'header',
-                bodyTmpl: 'body'
+                bodyTmpl: 'body',
+                source: function () {}
             });
         });
 
@@ -27,11 +28,6 @@ define([
                 expect(column.sorting).toBe('asc');
             });
 
-            it('apply sorting in other direction', function () {
-                column.sort(true).sort(true);
-                expect(column.sorting).toBe('desc');
-            });
-
             it('remove sorting', function () {
                 column.sort(false);
                 expect(column.sorting).toBeFalsy();
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/date.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/date.test.js
index e93209a5dfd04fbb6d897b650bc94cc7157b4f73..bee9a76a8ed390ab1aa8d6aaa8c5f5a13b2e6314 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/date.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/date.test.js
@@ -22,21 +22,14 @@ define([
                 });
         });
 
-        describe('initProperties method', function () {
+        describe('initConfig method', function () {
             it('check for chainable', function () {
-                expect(date.initProperties()).toEqual(date);
+                expect(date.initConfig()).toEqual(date);
             });
             it('check for extend', function () {
-                date.initProperties();
+                date.initConfig();
                 expect(date.dateFormat).toBeDefined();
             });
         });
-
-        describe('getLabel method', function () {
-            it('check format', function () {
-                date.dateFormat = dateFormat;
-                expect(date.getLabel(dateRaw)).toBe(dateFormatted);
-            });
-        });
     });
 });
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/select.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/select.test.js
index 9b9e0b35cf3ebc05a49ec2dbc26ebd15ae338d41..3179490ab1ed62391841b17df6f459e52b106db6 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/select.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/select.test.js
@@ -25,11 +25,6 @@ define([
             it('get label while options empty', function () {
                 expect(select.getLabel(2)).toBe('');
             });
-
-            it('get label for existed value', function () {
-                select.options = opts;
-                expect(select.getLabel(2)).toBe('b');
-            });
         });
     });
 });
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/bookmarks/bookmarks.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/bookmarks/bookmarks.test.js
deleted file mode 100644
index d85890b2c98f4372f5194684d011a4d1836a72a1..0000000000000000000000000000000000000000
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/bookmarks/bookmarks.test.js
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-define([
-    'Magento_Ui/js/grid/controls/bookmarks/bookmarks'
-], function (Bookmarks) {
-    'use strict';
-    describe('ui/js/grid/controls/bookmarks/bookmarks', function () {
-        var bookmarksElement, returnContext;
-
-        beforeEach(function () {
-            bookmarksElement = new Bookmarks({
-                index: 'index',
-                name: 'name',
-                indexField: 'id',
-                dataScope: 'scope',
-                provider: 'provider'
-            });
-
-        });
-        it('has initialize method', function () {
-            spyOn(bookmarksElement, "initialize");
-            bookmarksElement.initialize();
-            expect(bookmarksElement.initialize).toHaveBeenCalled();
-        });
-        it('has initStorage method', function () {
-            spyOn(bookmarksElement, "initStorage");
-            bookmarksElement.initStorage();
-            expect(bookmarksElement.initStorage).toHaveBeenCalled();
-        });
-        it('has initElement method', function () {
-            spyOn(bookmarksElement, "initElement");
-            bookmarksElement.initElement();
-            expect(bookmarksElement.initElement).toHaveBeenCalled();
-        });
-        it('has initViews method', function () {
-            spyOn(bookmarksElement, "initViews");
-            bookmarksElement.initViews();
-            expect(bookmarksElement.initViews).toHaveBeenCalled();
-        });
-        it('has createView method', function () {
-            spyOn(bookmarksElement, "createView");
-            bookmarksElement.createView();
-            expect(bookmarksElement.createView).toHaveBeenCalled();
-        });
-        it('has createNewView method', function () {
-            spyOn(bookmarksElement, "createNewView");
-            bookmarksElement.createNewView();
-            expect(bookmarksElement.createNewView).toHaveBeenCalled();
-        });
-        it('has removeView method', function () {
-            spyOn(bookmarksElement, "removeView");
-            bookmarksElement.removeView();
-            expect(bookmarksElement.removeView).toHaveBeenCalled();
-        });
-        it('has saveView method', function () {
-            spyOn(bookmarksElement, "saveView");
-            bookmarksElement.saveView();
-            expect(bookmarksElement.saveView).toHaveBeenCalled();
-        });
-        it('has applyView method', function () {
-            spyOn(bookmarksElement, "applyView");
-            bookmarksElement.applyView();
-            expect(bookmarksElement.applyView).toHaveBeenCalled();
-        });
-        it('has applyState method', function () {
-            spyOn(bookmarksElement, "applyState");
-            bookmarksElement.applyState();
-            expect(bookmarksElement.applyState).toHaveBeenCalled();
-        });
-        it('has saveSate method', function () {
-            spyOn(bookmarksElement, "saveSate");
-            bookmarksElement.saveSate();
-            expect(bookmarksElement.saveSate).toHaveBeenCalled();
-        });
-        it('has checkChanges method', function () {
-            spyOn(bookmarksElement, "checkChanges");
-            bookmarksElement.checkChanges();
-            expect(bookmarksElement.checkChanges).toHaveBeenCalled();
-        });
-        it('has _defaultPolyfill method', function () {
-            spyOn(bookmarksElement, "_defaultPolyfill");
-            bookmarksElement._defaultPolyfill();
-            expect(bookmarksElement._defaultPolyfill).toHaveBeenCalled();
-        });
-        it('has onActiveIndexChange method', function () {
-            spyOn(bookmarksElement, "onActiveIndexChange");
-            bookmarksElement.onActiveIndexChange();
-            expect(bookmarksElement.onActiveIndexChange).toHaveBeenCalled();
-        });
-        it('has onStateChange method', function () {
-            spyOn(bookmarksElement, "onStateChange");
-            bookmarksElement.onStateChange();
-            expect(bookmarksElement.onStateChange).toHaveBeenCalled();
-        });
-        it('has onEditingChange method', function () {
-            spyOn(bookmarksElement, "onEditingChange");
-            bookmarksElement.onEditingChange();
-            expect(bookmarksElement.onEditingChange).toHaveBeenCalled();
-        });
-    });
-});
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/bookmarks/view.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/bookmarks/view.test.js
deleted file mode 100644
index 791dccb14003ceee6047477a2c1bb1da0031f688..0000000000000000000000000000000000000000
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/bookmarks/view.test.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-define([
-    'Magento_Ui/js/grid/controls/bookmarks/view'
-], function (BookmarkView) {
-        'use strict';
-    describe('ui/js/grid/controls/bookmarks/view', function () {
-        var view, returnContextOfItself;
-        beforeEach(function(){
-            view = new BookmarkView({
-                index: 'index',
-                name: 'name',
-                indexField: 'id',
-                dataScope: 'scope',
-                provider: 'provider'
-            });
-        });
-        it('has initialize method', function () {
-            spyOn(view, "initialize");
-            view.initialize();
-            expect(view.initialize).toHaveBeenCalled();
-        });
-        it('has initObservable method', function () {
-            spyOn(view, "initObservable");
-            view.initObservable();
-            expect(view.initObservable).toHaveBeenCalled();
-        });
-        it('has getData method', function () {
-            spyOn(view, "getData");
-            view.getData();
-            expect(view.getData).toHaveBeenCalled();
-        });
-        it('has setData method', function () {
-            spyOn(view, "setData");
-            view.setData();
-            expect(view.setData).toHaveBeenCalled();
-        });
-        it('has syncLabel method', function () {
-            spyOn(view, "syncLabel");
-            view.syncLabel();
-            expect(view.syncLabel).toHaveBeenCalled();
-        });
-        it('has startEdit method', function () {
-            spyOn(view, "startEdit");
-            view.startEdit();
-            expect(view.startEdit).toHaveBeenCalled();
-        });
-        it('has exportView method', function () {
-            spyOn(view, "exportView");
-            view.exportView();
-            expect(view.exportView).toHaveBeenCalled();
-        });
-        it('has onActivate method', function () {
-            spyOn(view, "onActivate");
-            view.onActivate();
-            expect(view.onActivate).toHaveBeenCalled();
-        });
-        it('has onActiveChange method', function () {
-            spyOn(view, "onActiveChange");
-            view.onActiveChange();
-            expect(view.onActiveChange).toHaveBeenCalled();
-        });
-    })
-});
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/editing/bulk.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/editing/bulk.test.js
index 094ad409e5eb4415672702fb38eb219070b2fe54..bdbffbff347fe27c18b13b1c17b79f175f724ec2 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/editing/bulk.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/editing/bulk.test.js
@@ -13,6 +13,7 @@ define([
 
         beforeEach(function () {
             bulkObj = new Bulk();
+            bulkObj.editor = jasmine.createSpy('editor');
         });
         it('has initObservable', function () {
             expect(bulkObj).toBeDefined();
@@ -33,5 +34,5 @@ define([
             bulkObj.updateState();
             expect(bulkObj.updateState).toHaveBeenCalled();
         });
-    })
-});
\ No newline at end of file
+    });
+});
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/filters.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/filters.test.js
index 0555f056f5e90822b1aca09f39c1c27b08f7cf8a..05a65b038f3e3783d2af10d1ab75f1a2c0ee135f 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/filters.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/filters.test.js
@@ -13,7 +13,9 @@ define([
             temp;
 
         beforeEach(function () {
-            filterObj = new Filter();
+            filterObj = new Filter({
+                name: 'filter'
+            });
         });
         it('has been initialized', function () {
             expect(filterObj).toBeDefined();
@@ -39,16 +41,6 @@ define([
             temp = filterObj.cancel();
             expect(temp).toBeDefined();
         });
-        it('has isOpened method', function () {
-            filterObj.opened = function () {
-                return true;
-            };
-            filterObj.hasVisible = function () {
-                return true;
-            };
-            temp = filterObj.isOpened();
-            expect(temp).toBeTruthy();
-        });
         it('has isFilterVisible method', function () {
             temp = {
                 visible: function () {
@@ -69,15 +61,5 @@ define([
             filterObj.hasVisible();
             expect(filterObj.hasVisible).toHaveBeenCalled();
         });
-        it('has extractActive method', function () {
-            spyOn(filterObj, 'extractActive');
-            filterObj.extractActive();
-            expect(filterObj.extractActive).toHaveBeenCalled();
-        });
-        it('has extractPreviews method', function () {
-            spyOn(filterObj, 'extractPreviews');
-            filterObj.extractPreviews();
-            expect(filterObj.extractPreviews).toHaveBeenCalled();
-        });
     });
-});
\ No newline at end of file
+});
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/range.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/range.test.js
index 44640d6ef206367191e630c36dcdd5271982e268..c2f798927fa8e34fa453d505f532371ee0e801e0 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/range.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/range.test.js
@@ -28,18 +28,6 @@ define([
             group.elems.push({id:1}, {id:1});
             expect(group.elems()).not.toEqual([]);
         });
-        it('Check for reset elements.', function () {
-            var elem = {
-                value: false,
-                reset: function() {
-                    this.value = true;
-                }
-            };
-
-            group.elems.push(elem);
-            expect(group.reset()).toBe(group);
-            expect(group.elems.first().value).toBe(true);
-        });
         it('Check for clear elements.', function () {
             var elem = {
                 value: 'text',
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js
index 36c2823eaf9e62706bc4d0d12174fedad4d25049..a240e5cfd432597d4bb38e10957b4495d4ed48b2 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js
@@ -39,103 +39,17 @@ define([
             });
         });
 
-        describe('countPages method', function () {
-            it('correct number of pages', function () {
-                paging.countPages();
-                expect(paging.pages).toBe(4);
-            });
-
-            it('if no records', function () {
-                paging.totalRecords = 0;
-                paging.countPages();
-                expect(paging.pages).toBe(1);
-            });
-        });
-
-        describe('page manipualations', function () {
-            it('setPage method', function () {
-                paging.setPage(2);
-                expect(paging.current).toBe(2);
-            });
-
-            it('next', function () {
-                paging.current = 1;
-                paging.next();
-                expect(paging.current).toBe(2);
-            });
-
-            it('next out of boundary', function () {
-                paging.current = 4;
-                paging.next();
-                expect(paging.current).toBe(4);
-            });
-
-            it('prev', function () {
-                paging.current = 4;
-                paging.prev();
-                expect(paging.current).toBe(3);
-            });
-
-            it('prev out of boundary', function () {
-                paging.current = 1;
-                paging.prev();
-                expect(paging.current).toBe(1);
-            });
-
-            it('goFirst', function () {
-                paging.goFirst();
-                expect(paging.current).toBe(1);
-            });
-
-            it('goLast', function () {
-                paging.goLast();
-                expect(paging.current).toBe(4);
-            });
-
-            it('isFirst for 1st page', function () {
-                paging.current = 1;
-                expect(paging.isFirst()).toBeTruthy();
-            });
-
-            it('isFirst for 2nd page', function () {
-                paging.current = 2;
-                expect(paging.isFirst()).toBeFalsy();
-            });
-
-            it('isLast for last page', function () {
-                paging.current = 4;
-                expect(paging.isLast()).toBeTruthy();
-            });
-
-            it('isLast for first page', function () {
-                paging.current = 1;
-                expect(paging.isLast()).toBeFalsy();
-            });
-        });
-
-        describe('countPages method', function () {
-            it('correct number of pages', function () {
-                paging.countPages();
-                expect(paging.pages).toBe(4);
-            });
-
-            it('if no records', function () {
-                paging.totalRecords = 0;
-                paging.countPages();
-                expect(paging.pages).toBe(1);
-            });
-        });
-
         describe('onPagesChange method', function () {
             it('pages amount became less than current', function () {
                 paging.current = 4;
                 expect(paging.current).toBe(4);
-                paging.onPagesChange(2);
-                expect(paging.current).toBe(2);
+                paging.pageSize = 3;
+                paging.onPagesChange();
+                expect(paging.current).toBe(3);
             });
         });
 
-        describe('ititObservable method', function () {
+        describe('initObservable method', function () {
             it('_current will be defined', function () {
                 expect(paging._current).toBeDefined();
             });
@@ -144,14 +58,6 @@ define([
                 paging.current = 2;
                 expect(paging._current()).toBe(2);
             });
-
-            it('write into current', function () {
-                spyOn(paging, 'normalize').and.callThrough();
-                spyOn(paging._current, 'notifySubscribers');
-                paging._current(4);
-                expect(paging.current).toBe(4);
-                expect(paging._current.notifySubscribers).toHaveBeenCalledWith(4);
-            });
         });
     });
 });
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/resize.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/resize.test.js
index 948bfb84a85da7621273661ccf8da12483e196ab..4cbb9e73d5ae770bb1121b635dbf7ab4da260ecc 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/resize.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/resize.test.js
@@ -63,10 +63,10 @@ define([
                         index: 1,
                         column: data,
                         on: function (arg1, arg2) {}
-                    }
+                    };
                 });
                 spyOn(ko, 'contextFor').and.callFake(function () {
-                    return {$index: 1, $parent: obj}
+                    return {$index: 1, $parent: obj};
                 });
                 $._data = jasmine.createSpy().and.callFake(function () {
                     return {
@@ -82,45 +82,6 @@ define([
                 type = typeof obj.initColumn;
                 expect(type).toEqual('function');
             });
-            it('Check call "this.getDefaultWidth" method', function () {
-                spyOn(obj, 'getDefaultWidth');
-                obj.initColumn('magento');
-                expect(obj.getDefaultWidth).toHaveBeenCalledWith('magento');
-            });
-            it('Check call "this.hasColumn" method', function () {
-                spyOn(obj, 'hasColumn').and.callFake(function () {
-                    return false;
-                });
-                obj.initColumn('magento');
-                expect(obj.hasColumn).toHaveBeenCalled();
-            });
-            it('Check call "this.initResizableElement" method', function () {
-                spyOn(obj, 'hasColumn').and.callFake(function () {
-                    return false;
-                });
-                spyOn(obj, 'initResizableElement').and.callFake(function (arg) {
-                    return true;
-                });
-                obj.initColumn('magento');
-                expect(obj.initResizableElement).toHaveBeenCalled();
-            });
-            it('Check call "this.setStopPropagationHandler" method', function () {
-                spyOn(obj, 'hasColumn').and.callFake(function () {
-                    return false;
-                });
-                spyOn(obj, 'setStopPropagationHandler').and.callFake(function (arg) {
-                    return true;
-                });
-                obj.initColumn('magento');
-                expect(obj.setStopPropagationHandler).toHaveBeenCalledWith('magento');
-            });
-            it('Check call "this.refreshLastColumn" method', function () {
-                spyOn(obj, 'refreshLastColumn').and.callFake(function (arg) {
-                    return true;
-                });
-                obj.initColumn('magento');
-                expect(obj.refreshLastColumn).toHaveBeenCalledWith('magento');
-            });
         });
         describe('"initResizableElement" method', function () {
             beforeEach(function(){
@@ -194,9 +155,9 @@ define([
                     }
                 });
                 spyOn(ko, 'contextFor').and.callFake(function () {
-                    return {$index: ko.observable(1), $parent: obj}
+                    return {$index: ko.observable(1), $parent: obj};
                 });
-                spyOn(obj, 'getNextElement').and.callFake(function () {
+                spyOn(obj, 'getNextElements').and.callFake(function () {
                     return true;
                 });
                 event = {stopImmediatePropagation: function(){}}
@@ -215,9 +176,9 @@ define([
                 obj.mousedownHandler(event);
                 expect(obj.hasColumn).toHaveBeenCalled();
             });
-            it('Check call "this.getNextElement" method', function () {
+            it('Check call "this.getNextElements" method', function () {
                 obj.mousedownHandler(event);
-                expect(obj.getNextElement).toHaveBeenCalled();
+                expect(obj.getNextElements).toHaveBeenCalled();
             });
         });
         describe('"mousemoveHandler" method', function () {
@@ -261,7 +222,7 @@ define([
                 expect(obj.storageColumnsData[2]).toEqual(200);
             });
         });
-        describe('"getNextElement" method', function () {
+        describe('"getNextElements" method', function () {
             beforeEach(function(){
                 spyOn(ko, 'dataFor').and.callFake(function (data) {
                     return {
@@ -275,24 +236,24 @@ define([
                 });
             });
             it('Check for defined ', function () {
-                expect(obj.hasOwnProperty('getNextElement')).toBeDefined();
+                expect(obj.hasOwnProperty('getNextElements')).toBeDefined();
             });
             it('Check method type', function () {
-                type = typeof obj.getNextElement;
+                type = typeof obj.getNextElements;
                 expect(type).toEqual('function');
             });
             it('Check call "this.hasColumn" method', function () {
                 spyOn(obj, 'hasColumn').and.callFake(function () {
                     return 'magento';
                 });
-                obj.getNextElement('magento');
+                obj.getNextElements('magento');
                 expect(obj.hasColumn).toHaveBeenCalled();
             });
             it('Check returned value', function () {
                 spyOn(obj, 'hasColumn').and.callFake(function () {
                     return 'magento';
                 });
-                expect(obj.getNextElement('magento')).toEqual('magento');
+                expect(obj.getNextElements('magento')).toEqual('magento');
             });
         });
         describe('"getDefaultWidth" method', function () {
@@ -337,21 +298,11 @@ define([
                 arg = { index: 'magento' };
                 expect(typeof obj.hasColumn(arg, false)).toEqual('boolean');
             });
-            it('Must return false if object columnsElements has not model.index property', function () {
-                arg = { index: 'magento' };
-                obj.columnsElements = {};
-                expect(obj.hasColumn(arg, false)).toEqual(false);
-            });
             it('Must return true if object columnsElements has  model.index property', function () {
                 arg = { index: 'magento' };
                 obj.columnsElements = {magento: 'magentoProp'};
                 expect(obj.hasColumn(arg, false)).toEqual(true);
             });
-            it('Must return property if object columnsElements has property and second argument is true', function () {
-                arg = { index: 'magento' };
-                obj.columnsElements = {magento: 'magentoProp'};
-                expect(obj.hasColumn(arg, true)).toEqual('magentoProp');
-            });
         });
         describe('"hasRow" method', function () {
             it('Check for defined ', function () {
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/search/search.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/search/search.test.js
index b407fe3bebeae0153d60fe37a76953a50a1d72f6..e10061263d13a14214e50ab1266f809c96ec0883 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/search/search.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/search/search.test.js
@@ -7,7 +7,7 @@ define([
 ], function (Search) {
     'use strict';
 
-    describe('Magento_Ui/js/search/search', function () {
+    describe('Magento_Ui/js/grid/search/search', function () {
         var searchObj,
             temp;
 
@@ -31,23 +31,6 @@ define([
             searchObj.initChips();
             expect(searchObj.chips).toHaveBeenCalled();
         });
-        it('has clear', function () {
-            spyOn(searchObj, 'value');
-            searchObj.clear();
-            expect(searchObj.value).toHaveBeenCalled();
-        });
-        it('has clear', function () {
-            spyOn(searchObj, 'inputValue');
-            searchObj.cancel();
-            expect(searchObj.inputValue).toHaveBeenCalled();
-        });
-        it('has apply', function () {
-            spyOn(searchObj, 'value');
-            spyOn(searchObj, 'inputValue');
-            searchObj.apply();
-            expect(searchObj.value).toHaveBeenCalled();
-            expect(searchObj.inputValue).toHaveBeenCalled();
-        });
         it('has updatePreview', function () {
             spyOn(searchObj, 'updatePreview');
             searchObj.updatePreview();
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/sticky/sticky.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/sticky/sticky.test.js
index 4c2b68d8fcd01046895f88589d339948b032b269..426b453ab42852caf01763e5d6f73ff11933fffb 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/sticky/sticky.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/sticky/sticky.test.js
@@ -135,10 +135,13 @@ define([
                 stickyObj.resetToTop();
                 expect(stickyObj.resetToTop).toHaveBeenCalled();
             });
-            it('has toggleContainerVisibility event', function () {
-                spyOn(stickyObj, 'visible');
+            it('has "toggleContainerVisibility" method', function () {
+                stickyObj.visible = false;
                 stickyObj.toggleContainerVisibility();
-                expect(stickyObj.visible).toHaveBeenCalled();
+                expect(stickyObj.visible).toEqual(true);
+                stickyObj.visible = true;
+                stickyObj.toggleContainerVisibility();
+                expect(stickyObj.visible).toEqual(false);
             });
             it('has adjustContainerElemsWidth event', function () {
                 stickyObj.resizeContainer = function(){
@@ -156,17 +159,6 @@ define([
                 stickyObj.adjustOffset();
                 expect(stickyObj.adjustOffset).toHaveBeenCalled();
             });
-            it('has checkPos event', function () {
-                stickyObj.visible = function(){
-                    return false;
-                };
-                stickyObj.getMustBeSticky = function(){
-                    return false;
-                };
-
-                data = stickyObj.checkPos();
-                expect(data).toBeDefined();
-            })
         });
     })
 });
\ No newline at end of file
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/core.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/core.test.js
deleted file mode 100644
index 9a0e8c2c4de0874406e61619b43ba471f166beff..0000000000000000000000000000000000000000
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/core.test.js
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-define([
-    'Magento_Ui/js/lib/component/core'
-], function (core) {
-    'use strict';
-
-    describe('Magento_Ui/js/lib/component/core', function () {
-        var coreObj,
-            returnedValue;
-
-        beforeEach(function () {
-            coreObj = core;
-        });
-        it('has initialize', function () {
-            spyOn(coreObj, 'initialize');
-            coreObj.initialize();
-            expect(coreObj.initialize).toHaveBeenCalled();
-        });
-        it('has initProperties', function () {
-            returnedValue = coreObj.initProperties();
-            expect(typeof returnedValue).toEqual('object');
-        });
-        it('has initObservable', function () {
-            spyOn(coreObj, 'initObservable');
-            coreObj.initObservable();
-            expect(coreObj.initObservable).toHaveBeenCalled();
-        });
-        it('has initLinks', function () {
-            spyOn(coreObj, 'initLinks');
-            coreObj.initLinks();
-            expect(coreObj.initLinks).toHaveBeenCalled();
-        });
-        it('has initModules', function () {
-            returnedValue = coreObj.initModules();
-            expect(typeof returnedValue).toEqual('object');
-        });
-        it('has initUnique', function () {
-            returnedValue = coreObj.initUnique();
-            expect(typeof returnedValue).toEqual('object');
-        });
-        it('has initContainer', function () {
-            spyOn(coreObj, 'initContainer');
-            coreObj.initContainer();
-            expect(coreObj.initContainer).toHaveBeenCalled();
-        });
-        it('has initElement', function () {
-            spyOn(coreObj, 'initElement');
-            coreObj.initElement();
-            expect(coreObj.initElement).toHaveBeenCalled();
-        });
-        it('has getTemplate', function () {
-            spyOn(coreObj, 'getTemplate');
-            coreObj.getTemplate();
-            expect(coreObj.getTemplate).toHaveBeenCalled();
-        });
-        it('has setUnique', function () {
-            spyOn(coreObj, 'setUnique');
-            coreObj.setUnique();
-            expect(coreObj.setUnique).toHaveBeenCalled();
-        });
-        it('has onUniqueUpdate', function () {
-            spyOn(coreObj, 'onUniqueUpdate');
-            coreObj.onUniqueUpdate();
-            expect(coreObj.onUniqueUpdate).toHaveBeenCalled();
-        });
-    });
-});
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/links.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/links.test.js
index cf122dbc31fdfe14c0e7654abd232f2558562447..ff17bd826b5c212cf7e2fe624d7da70a3fca2177 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/links.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/links.test.js
@@ -19,9 +19,6 @@ define([
             };
 
         });
-        it('has defaults', function () {
-            expect(typeof linksObj.defaults).toEqual('object');
-        });
         it('has setLinks method', function () {
             returnedValue = linksObj.setLinks(undefined, 'imports');
             expect(typeof returnedValue).toEqual('object');
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/manip.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/manip.test.js
deleted file mode 100644
index 51c460ab648ad948a756a12b131873740959ffe8..0000000000000000000000000000000000000000
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/manip.test.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-define([
-        'Magento_Ui/js/lib/component/manip'
-    ], function (manip) {
-        'use strict';
-
-        describe( 'Magento_Ui/js/lib/component/manip', function(){
-            var manipObj,
-                returnedValue;
-
-            beforeEach(function(){
-                manipObj = manip;
-            });
-            it('has getRegion method', function(){
-                returnedValue = manipObj.getRegion("region");
-                expect(returnedValue).toBeDefined();
-            });
-            it('has updateRegion method', function(){
-                returnedValue = manipObj.updateRegion([],"region");
-                expect(typeof returnedValue).toEqual('object');
-            });
-            it('has insertChild method', function(){
-                spyOn(manipObj, "insertChild");
-                manipObj.insertChild();
-                expect(manipObj.insertChild).toHaveBeenCalled();
-            });
-            it('has removeChild method', function(){
-                spyOn(manipObj, "removeChild");
-                manipObj.removeChild();
-                expect(manipObj.removeChild).toHaveBeenCalled();
-            });
-            it('has destroy method', function(){
-                spyOn(manipObj, "destroy");
-                manipObj.destroy();
-                expect(manipObj.destroy).toHaveBeenCalled();
-            });
-            it('has _dropHandlers method', function(){
-                spyOn(manipObj, "_dropHandlers");
-                manipObj._dropHandlers();
-                expect(manipObj._dropHandlers).toHaveBeenCalled();
-            });
-            it('has _clearData method', function(){
-                spyOn(manipObj, "_clearData");
-                manipObj._clearData();
-                expect(manipObj._clearData).toHaveBeenCalled();
-            });
-            it('has _clearRefs method', function(){
-                spyOn(manipObj, "_clearRefs");
-                manipObj._clearRefs();
-                expect(manipObj._clearRefs).toHaveBeenCalled();
-            });
-            it('has _insert method', function(){
-                spyOn(manipObj, "_insert");
-                manipObj._insert();
-                expect(manipObj._insert).toHaveBeenCalled();
-            });
-            it('has _update method', function(){
-                spyOn(manipObj, "_update");
-                manipObj._update();
-                expect(manipObj._update).toHaveBeenCalled();
-            });
-
-        });
-    });
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/provider.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/provider.test.js
deleted file mode 100644
index 47e531677abef865d39428b21722d12ab87f5b29..0000000000000000000000000000000000000000
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/provider.test.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-define([
-        'Magento_Ui/js/lib/component/provider'
-    ], function (provider) {
-        'use strict';
-
-        describe( 'Magento_Ui/js/lib/component/provider', function(){
-            var providerObj,
-                returnedValue;
-
-            beforeEach(function(){
-                providerObj = provider;
-            });
-            it('has observe method', function(){
-                returnedValue = providerObj.observe("elems");
-                expect(typeof  returnedValue).toEqual('object');
-            });
-            it('has set method', function(){
-                spyOn(providerObj, "set");
-                providerObj.set();
-                expect(providerObj.set).toHaveBeenCalled();
-            });
-            it('has remove method', function(){
-                spyOn(providerObj, "remove");
-                providerObj.remove();
-                expect(providerObj.remove).toHaveBeenCalled();
-            });
-            it('has restore method', function(){
-                spyOn(providerObj, "restore");
-                providerObj.restore();
-                expect(providerObj.restore).toHaveBeenCalled();
-            });
-            it('has removeStored method', function(){
-                spyOn(providerObj, "removeStored");
-                providerObj.removeStored();
-                expect(providerObj.removeStored).toHaveBeenCalled();
-            });
-        });
-    });
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/traversal.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/traversal.test.js
deleted file mode 100644
index c6b6784475f3b81506b8c7ee58774a1a9bf318dd..0000000000000000000000000000000000000000
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/traversal.test.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-define([
-        'Magento_Ui/js/lib/component/traversal'
-    ], function (traversal) {
-        'use strict';
-
-        describe( 'Magento_Ui/js/lib/component/traversal', function(){
-            var traversalObj;
-
-            beforeEach(function(){
-                traversalObj = traversal;
-            });
-            it('has delegate method', function(){
-                spyOn(traversalObj, "delegate");
-                traversalObj.delegate();
-                expect(traversalObj.delegate).toHaveBeenCalled();
-            });
-        });
-    });
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/ko/bind/i18n.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/ko/bind/i18n.test.js
index 8d0a99361ea547eb8b1894346861c20a6fceae42..8f7485a2f0bed94f9460be567d8e39c2f7ded2cb 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/ko/bind/i18n.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/ko/bind/i18n.test.js
@@ -82,36 +82,5 @@ define([
             expect(elWithVariable.attr(dataTranslateAttrName))
                 .toEqual(dataTranslateAttr.replace(/\$/g, variableText).replace(/\&/g, variableText));
         });
-
-        it('if inline translation is on, ' +
-        'and there is translation for this text,' +
-        ' set translated text for element', function () {
-            turnOnInlineTranslation();
-            $.mage.translate.add(staticText, staticTextTranslatedRaw);
-            $.mage.translate.add(variableText, variableTranslatedRaw);
-            spyOn($.mage.translate, 'parsedTranslate').and.callThrough();
-
-            context.config.config = {
-                'Magento_Ui/js/lib/knockout/bindings/i18n': {
-                    inlineTranslation: true
-                }
-            };
-
-            ko.applyBindingsToNode(elWithStaticText[0], {
-                i18n: staticText
-            });
-            ko.applyBindingsToNode(elWithVariable[0], {
-                i18n: variable
-            });
-
-            expect($.mage.translate.parsedTranslate).toHaveBeenCalledWith(staticText);
-            expect($.mage.translate.parsedTranslate).toHaveBeenCalledWith(variableText);
-            expect(elWithStaticText.text()).toEqual(staticTextTranslated);
-            expect(elWithVariable.text()).toEqual(variableTranslated);
-            expect(elWithStaticText.attr(dataTranslateAttrName))
-                .toEqual(dataTranslateAttr.replace(/\$/g, staticText).replace(/\&/g, staticTextTranslated));
-            expect(elWithVariable.attr(dataTranslateAttrName))
-                .toEqual(dataTranslateAttr.replace(/\$/g, variableText).replace(/\&/g, variableTranslated));
-        });
     });
 });
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/events.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/events.test.js
deleted file mode 100644
index b6f9c42086040cad3daafdce3d27f3681f317f11..0000000000000000000000000000000000000000
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/events.test.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-
-define([
-    'Magento_Ui/js/lib/registry/events'
-], function (EventBus) {
-    'use strict';
-
-    describe('Magento_Ui/js/lib/registry/events', function () {
-        var storage = {
-                has : function(){
-                    return false;
-                },
-                get : function(){
-                    return [];
-                }
-            },
-            eventsClass = new EventBus(storage);
-
-        describe('"resolve" method', function () {
-            it('Check for defined ', function () {
-                expect(eventsClass.resolve()).toBeDefined();
-            });
-            it('Check answer type', function () {
-                var type = typeof(eventsClass.resolve());
-
-                expect(type).toEqual('object');
-            });
-        });
-        describe('"wait" method', function () {
-            it('Check for defined ', function () {
-                expect(eventsClass.wait([],{})).toBeDefined();
-            });
-            it('Check return object property "requests" defined', function () {
-                var thisObject = eventsClass.wait([],{}).requests;
-
-                expect(thisObject).toBeDefined();
-            });
-            it('Check return object property "requests" type', function () {
-                var thisObject = typeof(eventsClass.wait([],{}).requests);
-
-                expect(thisObject).toEqual('object');
-            });
-        });
-        describe('"_resolve" method', function () {
-            it('Check completion method', function () {
-                eventsClass.request = [{
-                    callback: function(){return true;},
-                    deps: {}
-                }];
-                expect(eventsClass._resolve(0)).toEqual(false);
-            });
-        });
-    });
-});
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/registry.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/registry.test.js
index fd814d0a68fd41a79daf74825595cbb402a6f752..a45deb1df23afc9263ad1476732ce58c912e6752 100644
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/registry.test.js
+++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/registry.test.js
@@ -38,13 +38,6 @@ define([
 
                 expect(type).toEqual('object');
             });
-            it('Check assigned value after used method', function () {
-                var elem = 'test',
-                    prop = 'magento';
-                
-                registry.set(elem, prop);
-                expect(registry.storage.data.get(elem)).toEqual(prop);
-            });
         });
         describe('"registry.get" method', function () {
             it('Check for defined', function () {
@@ -63,14 +56,6 @@ define([
 
                 expect(type).toBeFalsy();
             });
-            it('Check called callback with arguments', function () {
-                var elems = ['magento'],
-                    callback = function () {};
-
-                registry.events.wait = jasmine.createSpy();
-                registry.get(elems, callback);
-                expect(registry.events.wait).toHaveBeenCalledWith(elems, callback);
-            });
         });
         describe('"registry.remove" method', function () {
             it('Check for defined', function () {
@@ -89,13 +74,6 @@ define([
 
                 expect(type).toEqual('object');
             });
-            it('Check called registry.storage.remove with arguments', function () {
-                var elems = ['magento'];
-
-                registry.storage.remove = jasmine.createSpy();
-                registry.remove(elems);
-                expect(registry.storage.remove).toHaveBeenCalledWith(elems);
-            });
         });
         describe('"registry.has" method', function () {
             it('Check for defined', function () {
@@ -106,24 +84,11 @@ define([
 
                 expect(type).toEqual('function');
             });
-            it('Check returned value if registry.storage has property', function () {
-                var name = 'magento';
-
-                registry.storage.data.set(name, 'magentoValue');
-                expect(registry.has(name)).toEqual(true);
-            });
             it('Check returned value if registry.storage has not property', function () {
                 var name = 'magentoNonProperty';
 
                 expect(registry.has(name)).toEqual(false);
             });
-            it('Check called registry.storage.has with arguments', function () {
-                var elems = ['magento'];
-
-                registry.storage.has = jasmine.createSpy();
-                registry.has(elems);
-                expect(registry.storage.has).toHaveBeenCalledWith(elems);
-            });
         });
         describe('"registry.async" method', function () {
             it('Check for defined', function () {
@@ -149,22 +114,6 @@ define([
 
                 expect(type).toEqual('object');
             });
-            it('Check registry.storage for defined', function () {
-                registry.create();
-                expect(registry.storage).toBeDefined();
-            });
-            it('Check registry.storage type', function () {
-                registry.create();
-                expect(typeof registry.storage).toEqual('object');
-            });
-            it('Check registry.events for defined', function () {
-                registry.create();
-                expect(registry.events).toBeDefined();
-            });
-            it('Check registry.events type', function () {
-                registry.create();
-                expect(typeof registry.events).toEqual('object');
-            });
         });
     });
 });
diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/storage.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/storage.test.js
deleted file mode 100644
index a2e2fd3c1206b79b1da01ebba2f4cdb248a25ed7..0000000000000000000000000000000000000000
--- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/registry/storage.test.js
+++ /dev/null
@@ -1,122 +0,0 @@
-/**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-/*eslint max-nested-callbacks: 0*/
-
-define([
-    'Magento_Ui/js/lib/registry/storage'
-], function (Storage) {
-    'use strict';
-
-    describe('Magento_Ui/js/lib/registry/storage', function () {
-        var storage = new Storage();
-        describe('"Storage constructor"', function () {
-            it('Check for defined', function () {
-                expect(storage).toBeDefined();
-            });
-            it('Check type', function () {
-                var type = typeof storage;
-
-                expect(type).toEqual('object');
-            });
-            it('Check storage.data for defined', function () {
-                var data = storage.data;
-
-                expect(typeof data).toEqual('object');
-            });
-        });
-        describe('"storage.get" method', function () {
-            it('Check for defined', function () {
-                expect(storage.hasOwnProperty('get')).toBeDefined();
-            });
-            it('Check type', function () {
-                var type = typeof storage.get;
-
-                expect(type).toEqual('function');
-            });
-            it('Check returned value if argument is array values', function () {
-                var elem = 'magento',
-                    value = 'magentoValue';
-
-                storage.data.set(elem, value);
-                expect(storage.get([elem])).toEqual([value]);
-            });
-            it('Check returned value if called withot arguments', function () {
-                expect(storage.get()).toEqual([]);
-            });
-        });
-        describe('"storage.set" method', function () {
-            it('Check for defined', function () {
-                expect(storage.hasOwnProperty('set')).toBeDefined();
-            });
-            it('Check type', function () {
-                var type = typeof storage.set;
-
-                expect(type).toEqual('function');
-            });
-            it('Check returned value for defined', function () {
-                expect(storage.set()).toBeDefined();
-            });
-            it('Check returned value type', function () {
-                var type = typeof storage.set();
-
-                expect(type).toEqual('object');
-            });
-            it('Check returned value if argument is "elem, value" ', function () {
-                var elem = 'magento',
-                    value = 'magentoValue';
-
-                storage.set(elem, value);
-                expect(storage.data.get(elem)).toEqual(value);
-            });
-        });
-        describe('"storage.remove" method', function () {
-            it('Check for defined', function () {
-                expect(storage.hasOwnProperty('remove')).toBeDefined();
-            });
-            it('Check type', function () {
-                var type = typeof storage.remove;
-
-                expect(type).toEqual('function');
-            });
-            it('Check returned value for defined', function () {
-                expect(storage.remove([])).toBeDefined();
-            });
-            it('Check returned value type', function () {
-                var type = typeof storage.remove([]);
-
-                expect(type).toEqual('object');
-            });
-            it('Check if called with argument "elem" ', function () {
-                var elem = 'magento',
-                    value = 'magentoValue';
-
-                storage.data.set(elem, value);
-                storage.remove([elem]);
-                expect(storage.data.get(elem)).not.toBeDefined();
-            });
-        });
-        describe('"storage.has" method', function () {
-            it('Check for defined', function () {
-                expect(storage.hasOwnProperty('has')).toBeDefined();
-            });
-            it('Check type', function () {
-                var type = typeof storage.has;
-
-                expect(type).toEqual('function');
-            });
-            it('Check returned value if data has element property', function () {
-                var elem = 'magento',
-                    value = 'magentoValue';
-
-                storage.data.set(elem, value);
-                expect(storage.has([elem])).toEqual(true);
-            });
-            it('Check returned value if data has not element property', function () {
-                expect(storage.has(['value'])).toEqual(false);
-            });
-        });
-    });
-});
diff --git a/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js b/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js
deleted file mode 100644
index 984bdf0cc3919ca35d55f82bd730aa129ea935e6..0000000000000000000000000000000000000000
--- a/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js
+++ /dev/null
@@ -1,154 +0,0 @@
-/**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-define([
-    'jquery',
-    'text!tests/assets/gallery/config.json',
-    'mage/gallery/gallery',
-    'magnifier/magnify'
-], function ($, config, gallery, magnifier) {
-
-    'use strict';
-
-    var body = $('body'),
-        galleryAPI,
-        conf = JSON.parse(config),
-        gallerySelector = '[data-gallery-role="gallery"]',
-        magnifierSelector = '[data-gallery-role="magnifier"]',
-        stageSelector = '[data-gallery-role="stage-shaft"]',
-        navSelector = '[data-gallery-role="nav-frame"]',
-        dotSelector = '[data-nav-type="dot"]',
-        navWrap = '[data-gallery-role="nav-wrap"]',
-        dataToUpdate = [
-            {
-                img: 'data:image/png;base64,' +
-                'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP4Xw8AAoABf5/NhYYAAAAASUVORK5CYII='
-            }, {
-                img: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAw' +
-                'CAAAAC0lEQVR42mP4Xw8AAoABf5/NhYYAAAAASUVORK5CYII='
-            }, {
-                img: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAw' +
-                'CAAAAC0lEQVR42mP4Xw8AAoABf5/NhYYAAAAASUVORK5CYII='
-            }, {
-                img: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAw' +
-                'CAAAAC0lEQVR42mP4Xw8AAoABf5/NhYYAAAAASUVORK5CYII='
-            }
-        ],
-        waitsFor = function (test, fn) {
-            if (test()) {
-                fn();
-            } else {
-                setTimeout(function () {
-                    waitsFor(test, fn);
-                }, 10);
-            }
-        };
-
-    gallery(magnifier(conf, body), body);
-
-    beforeEach(function () {
-        galleryAPI = $(gallerySelector).data('gallery');
-    });
-
-    describe('magnifier/magnify', function () {
-
-        if ('ontouchstart' in document.documentElement) {
-            it('magnifier is not initialized on mobile platforms', function () {
-                expect($(magnifierSelector).length).toBe(0);
-            });
-        } else {
-            it('magnifier is defined', function () {
-                expect($(gallerySelector).magnify).toBeDefined();
-                expect(typeof $(gallerySelector).magnify).toBe('function');
-                expect($(magnifierSelector).hasClass('hidden')).toBeTruthy();
-            });
-
-            it('magnifier is initialized on desktop platforms', function () {
-                expect($(magnifierSelector + ' img').attr('src')).toBe($(stageSelector + ' img').attr('src'));
-            });
-            it('magnifier appearing on event on desktop platforms', function () {
-                var ev = conf.magnifierOpts.eventType === 'click' ? 'click' : 'mouseover';
-                expect($($(magnifierSelector).children()[0]).hasClass('magnifier-large hidden')).toBeTruthy();
-                $(stageSelector + ' img').trigger(ev);
-                expect($($(magnifierSelector).children()[0]).hasClass('magnifier-large hidden')).toBeFalsy();
-                $(stageSelector + ' img').trigger('mouseleave');
-            });
-        }
-    });
-
-    describe('mage/gallery/gallery', function () {
-
-        it('gallery loaded', function () {
-            expect($(navSelector).length).toBe(conf.data.length);
-        });
-
-        it('show last', function () {
-            galleryAPI.last();
-            expect($(navSelector + ':eq(' + (conf.data.length - 1) + ')')
-                .attr('data-active') === 'true').toBeTruthy();
-        });
-
-        it('show first', function () {
-            galleryAPI.first();
-            expect($(navSelector + ':eq(0)').attr('data-active') === 'true').toBeTruthy();
-        });
-
-        it('show next', function () {
-            galleryAPI.next();
-            expect($(navSelector + ':eq(1)').attr('data-active') === 'true').toBeTruthy();
-        });
-
-        it('show previous', function () {
-            galleryAPI.prev();
-            expect($(navSelector + ':eq(0)').attr('data-active') === 'true').toBeTruthy();
-        });
-
-        it('show by number', function () {
-            galleryAPI.seek(3);
-            expect($(navSelector + ':eq(2)').attr('data-active') === 'true').toBeTruthy();
-        });
-
-        it('update options', function () {
-            expect($(navSelector).attr('data-nav-type') === 'thumb').toBeTruthy();
-            galleryAPI.updateOptions({
-                nav: 'dots'
-            });
-            expect($(dotSelector).length).toBe(conf.data.length);
-        });
-
-        it('update data', function () {
-            galleryAPI.updateData(dataToUpdate);
-            expect($(dotSelector).length).toBe(dataToUpdate.length);
-        });
-
-        it('breakpoints override configs', function () {
-            expect($('.fotorama__arr').css('display')).toBe('block');
-        });
-
-        it('fullscreen enter', function (done) {
-            expect($(navWrap).css('display') === 'block').toBeTruthy();
-            galleryAPI.fotorama.requestFullScreen();
-
-            waitsFor(function () {
-                return $(navWrap).css('display') !== 'block';
-            }, function () {
-                expect($(navWrap).css('display') === 'none').toBeTruthy();
-                done();
-            });
-        });
-
-        it('fullscreen exit', function (done) {
-            expect($(navWrap).css('display') === 'none').toBeTruthy();
-            galleryAPI.fotorama.cancelFullScreen();
-
-            waitsFor(function () {
-                return $(navWrap).css('display') !== 'none';
-            }, function () {
-                expect($(navWrap).css('display') === 'block').toBeTruthy();
-                done();
-            });
-        });
-
-    });
-});
diff --git a/dev/tests/static/get_github_changes.php b/dev/tests/static/get_github_changes.php
index c142aae18d8ecd5a4ab3fa895e32e5510b71683b..f332208cd17d0861dd1b28bd7096a0b3fe0066a5 100644
--- a/dev/tests/static/get_github_changes.php
+++ b/dev/tests/static/get_github_changes.php
@@ -12,9 +12,9 @@
 // @codingStandardsIgnoreFile
 
 define(
-'USAGE',
-<<<USAGE
-    php -f get_github_changes.php --
+    'USAGE',
+    <<<USAGE
+        php -f get_github_changes.php --
     --output-file="<output_file>"
     --base-path="<base_path>"
     --repo="<main_repo>"
@@ -36,6 +36,8 @@ $fileExtensions = explode(',', isset($options['file-extensions']) ? $options['fi
 
 $mainline = 'mainline_' . (string)rand(0, 9999);
 $repo = getRepo($options, $mainline);
+$branches = $repo->getBranches('--remotes');
+generateBranchesList($options['output-file'], $branches, $options['branch']);
 $changes = retrieveChangesAcrossForks($mainline, $repo, $options['branch']);
 $changedFiles = getChangedFiles($changes, $fileExtensions);
 generateChangedFilesList($options['output-file'], $changedFiles);
@@ -57,6 +59,25 @@ function generateChangedFilesList($outputFile, $changedFiles)
     fclose($changedFilesList);
 }
 
+/**
+ * Generates a file containing origin branches
+ *
+ * @param string $outputFile
+ * @param array $branches
+ * @param string $branchName
+ * @return void
+ */
+function generateBranchesList($outputFile, $branches, $branchName)
+{
+    $branchOutputFile = str_replace('changed_files', 'branches', $outputFile);
+    $branchesList = fopen($branchOutputFile, 'w');
+    fwrite($branchesList, $branchName . PHP_EOL);
+    foreach ($branches as $branch) {
+        fwrite($branchesList, substr(strrchr($branch, '/'), 1) . PHP_EOL);
+    }
+    fclose($branchesList);
+}
+
 /**
  * Gets list of changed files
  *
@@ -84,7 +105,7 @@ function getChangedFiles(array $changes, array $fileExtensions)
  *
  * @param array $options
  * @param string $mainline
- * @return array
+ * @return GitRepo
  * @throws Exception
  */
 function getRepo($options, $mainline)
@@ -203,6 +224,19 @@ class GitRepo
         $this->call(sprintf('fetch %s', $remoteAlias));
     }
 
+    /**
+     * Returns branches
+     *
+     * @param string $source
+     * @return array|mixed
+     */
+    public function getBranches($source = '--all')
+    {
+        $result = $this->call(sprintf('branch ' . $source));
+
+        return is_array($result) ? $result : [];
+    }
+
     /**
      * Returns files changes between branch and HEAD
      *
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/reference.txt b/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/reference.txt
index 836a928dc5a72cf6a517dc1ae7f1bbc61e62a763..e4078a959c7a89284e508a884229f69d80e2e25a 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/reference.txt
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/reference.txt
@@ -115,3 +115,4 @@ DoubleColon
 \Magento\TestModuleMessageQueueConfiguration\AsyncHandler
 \Magento\TestModuleMessageQueueConfiguration\SyncHandler
 \Magento\TestModuleAsyncAmqp\Model\AsyncTestData
+\Magento\Mtf\Client\ElementInterface
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php
index 87bd329ef3b5611475c6ee9486cdc9f27c4ea5fe..2f3d312fb41ffba1287bafd324a64ac751316d5c 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php
@@ -15,38 +15,49 @@ class ModuleDBChangeTest extends \PHPUnit_Framework_TestCase
     /**
      * @var string
      */
-    protected static $changedFilesPattern = __DIR__ . '/../_files/changed_files*';
+    private static $branchesFilesPattern = __DIR__ . '/../_files/branches*';
 
     /**
      * @var string
      */
-    protected static $changedFileList = '';
+    private static $changedFilesPattern = __DIR__ . '/../_files/changed_files*';
 
     /**
-     * @var string Path for Magento's composer.json
+     * @var string
      */
-    protected static $composerFilePath = BP . '/composer.json';
+    private static $changedFileList = '';
 
     /**
-     * @var bool Is tests executes on develop branch
+     * @var bool
      */
-    protected static $isOnDevVersion = false;
+    private static $actualBranch = false;
 
     /**
      *  Set changed files paths and list for all projects
      */
     public static function setUpBeforeClass()
     {
-        foreach (glob(self::$changedFilesPattern) as $changedFile) {
-            self::$changedFileList .= file_get_contents($changedFile) . PHP_EOL;
-        }
+        foreach (glob(self::$branchesFilesPattern) as $branchesFile) {
+            //get the current branchname from the first line
+            $branchName = trim(file($branchesFile)[0]);
+            if ($branchName === 'develop') {
+                self::$actualBranch = true;
+            } else {
+                //get current minor branch name
+                preg_match('|^(\d+\.\d+)|', $branchName, $minorBranch);
+                $branchName = $minorBranch[0];
+
+                //get all version branches
+                preg_match_all('|^(\d+\.\d+)|m', file_get_contents($branchesFile), $matches);
 
-        if (file_exists(self::$composerFilePath)) {
-            $jsonData = json_decode(file_get_contents(self::$composerFilePath));
-            if (substr((string) $jsonData->version, -4) == '-dev') {
-                self::$isOnDevVersion = true;
+                //check is this a latest release branch
+                self::$actualBranch = ($branchName == max($matches[0]));
             }
         }
+
+        foreach (glob(self::$changedFilesPattern) as $changedFile) {
+            self::$changedFileList .= file_get_contents($changedFile) . PHP_EOL;
+        }
     }
 
     /**
@@ -54,15 +65,14 @@ class ModuleDBChangeTest extends \PHPUnit_Framework_TestCase
      */
     public function testModuleXmlFiles()
     {
-        if (self::$isOnDevVersion) {
-            $this->markTestSkipped('This test isn\'t applicable to the developer version of Magento');
+        if (!self::$actualBranch) {
+            preg_match_all('|etc/module\.xml$|mi', self::$changedFileList, $matches);
+            $this->assertEmpty(
+                reset($matches),
+                'module.xml changes for patch releases in non-actual branches are not allowed:' . PHP_EOL .
+                implode(PHP_EOL, array_values(reset($matches)))
+            );
         }
-        preg_match_all('|etc/module\.xml$|mi', self::$changedFileList, $matches);
-        $this->assertEmpty(
-            reset($matches),
-            'module.xml changes for patch releases in non-actual branches are not allowed:' . PHP_EOL .
-            implode(PHP_EOL, array_values(reset($matches)))
-        );
     }
 
     /**
@@ -70,14 +80,13 @@ class ModuleDBChangeTest extends \PHPUnit_Framework_TestCase
      */
     public function testModuleSetupFiles()
     {
-        if (self::$isOnDevVersion) {
-            $this->markTestSkipped('This test isn\'t applicable to the developer version of Magento');
+        if (!self::$actualBranch) {
+            preg_match_all('|app/code/Magento/[^/]+/Setup/[^/]+$|mi', self::$changedFileList, $matches);
+            $this->assertEmpty(
+                reset($matches),
+                'Code with changes for DB schema or data in non-actual branches are not allowed:' . PHP_EOL .
+                implode(PHP_EOL, array_values(reset($matches)))
+            );
         }
-        preg_match_all('|app/code/Magento/[^/]+/Setup/[^/]+$|mi', self::$changedFileList, $matches);
-        $this->assertEmpty(
-            reset($matches),
-            'Code with changes for DB schema or data in non-actual branches are not allowed:' . PHP_EOL .
-            implode(PHP_EOL, array_values(reset($matches)))
-        );
     }
 }
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
index bc49ab15a7d54151759f7e183fb36a8a7b6571c6..2ce1bf02bf3896da26a633c158b77697876c4d02 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
@@ -2155,7 +2155,6 @@ return [
     ['addOrderedQty', 'Magento\Reports\Model\ResourceModel\Product\Collection'],
     ['prepareForProductsInCarts', 'Magento\Reports\Model\ResourceModel\Quote\Collection'],
     ['getOrdersSubSelect', 'Magento\Reports\Model\ResourceModel\Quote\Collection'],
-    ['isOrderIncrementIdUsed', 'Magento\Quote\Model\ResourceModel\Quote'],
     ['isStateProtected', 'Magento\Sales\Model\Order'],
     ['_getBundleOptions', 'Magento\Bundle\Block\Checkout\Cart\Item\Renderer'],
     ['_getSelectionFinalPrice', 'Magento\Bundle\Block\Checkout\Cart\Item\Renderer'],
diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js
index 66b72857d003397b8a756dc6aae9c0de70c58eeb..7b5100215200473f0610afaf27c922e4662cce8f 100755
--- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js
+++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js
@@ -53,6 +53,10 @@ define([
                 });
             }
 
+            if (jQuery.isReady) {
+                tinyMCE.dom.Event.domLoaded = true;
+            }
+
             tinyMCE.init(this.getSettings(mode));
         },
 
@@ -357,6 +361,8 @@ define([
             // escape special chars in directives url to use it in regular expression
             var url = this.makeDirectiveUrl('%directive%').replace(/([$^.?*!+:=()\[\]{}|\\])/g, '\\$1');
             var reg = new RegExp(url.replace('%directive%', '([a-zA-Z0-9,_-]+)'));
+            content = decodeURIComponent(content);
+
             return content.gsub(reg, function(match) {
                 return Base64.mageDecode(match[1]);
             }.bind(this));
diff --git a/package.json.sample b/package.json.sample
index 384aa88c65611a9e20892aade71488b31847ac5c..40169b3179052d98ad2c1a79baf48e376689f3c1 100644
--- a/package.json.sample
+++ b/package.json.sample
@@ -18,7 +18,7 @@
         "grunt-contrib-connect": "^0.9.0",
         "grunt-contrib-cssmin": "^0.10.0",
         "grunt-contrib-imagemin": "^0.9.2",
-        "grunt-contrib-jasmine": "^0.8.1",
+        "grunt-contrib-jasmine": "^1.0.0",
         "grunt-contrib-less": "^0.12.0",
         "grunt-contrib-watch": "^0.6.1",
         "grunt-eslint": "17.3.1",
diff --git a/setup/performance-toolkit/profiles/ce/attributeSets.xml b/setup/performance-toolkit/config/attributeSets.xml
similarity index 100%
rename from setup/performance-toolkit/profiles/ce/attributeSets.xml
rename to setup/performance-toolkit/config/attributeSets.xml
diff --git a/setup/performance-toolkit/profiles/ce/searchConfig.xml b/setup/performance-toolkit/config/searchConfig.xml
similarity index 100%
rename from setup/performance-toolkit/profiles/ce/searchConfig.xml
rename to setup/performance-toolkit/config/searchConfig.xml
diff --git a/setup/performance-toolkit/profiles/ce/searchTerms.xml b/setup/performance-toolkit/config/searchTerms.xml
similarity index 100%
rename from setup/performance-toolkit/profiles/ce/searchTerms.xml
rename to setup/performance-toolkit/config/searchTerms.xml
diff --git a/setup/performance-toolkit/profiles/ce/extra_large.xml b/setup/performance-toolkit/profiles/ce/extra_large.xml
index c9bf96ad4f4cab4cb8a6c1aacbe6e89a673e842c..fd1da116bc92b39fa23a3a4821daec93889fbad4 100644
--- a/setup/performance-toolkit/profiles/ce/extra_large.xml
+++ b/setup/performance-toolkit/profiles/ce/extra_large.xml
@@ -68,8 +68,8 @@
                 <set_scheduled>true</set_scheduled>
             </indexer>
         </indexers>
-        <xi:include href="searchTerms.xml" />
-        <xi:include href="searchConfig.xml" />
-        <xi:include href="attributeSets.xml" />
+        <xi:include href="../../config/searchTerms.xml" />
+        <xi:include href="../../config/searchConfig.xml" />
+        <xi:include href="../../config/attributeSets.xml" />
     </profile>
 </config>
diff --git a/setup/performance-toolkit/profiles/ce/large.xml b/setup/performance-toolkit/profiles/ce/large.xml
index 07e7ac33023b17d5d626986b76d84e88b3f7314b..d5d381fe059c95316d43ef88f56280c27494b197 100644
--- a/setup/performance-toolkit/profiles/ce/large.xml
+++ b/setup/performance-toolkit/profiles/ce/large.xml
@@ -68,8 +68,8 @@
                 <set_scheduled>true</set_scheduled>
             </indexer>
         </indexers>
-        <xi:include href="searchTerms.xml" />
-        <xi:include href="searchConfig.xml" />
-        <xi:include href="attributeSets.xml" />
+        <xi:include href="../../config/searchTerms.xml" />
+        <xi:include href="../../config/searchConfig.xml" />
+        <xi:include href="../../config/attributeSets.xml" />
     </profile>
 </config>
diff --git a/setup/performance-toolkit/profiles/ce/medium.xml b/setup/performance-toolkit/profiles/ce/medium.xml
index 6b1b289e823bab41a6d637350037b64c39e96935..95cd062fa74b6b94233066a6f0d0d3b296480b6b 100644
--- a/setup/performance-toolkit/profiles/ce/medium.xml
+++ b/setup/performance-toolkit/profiles/ce/medium.xml
@@ -68,8 +68,8 @@
                 <set_scheduled>false</set_scheduled>
             </indexer>
         </indexers>
-        <xi:include href="searchTerms.xml" />
-        <xi:include href="searchConfig.xml" />
-        <xi:include href="attributeSets.xml" />
+        <xi:include href="../../config/searchTerms.xml" />
+        <xi:include href="../../config/searchConfig.xml" />
+        <xi:include href="../../config/attributeSets.xml" />
     </profile>
 </config>
diff --git a/setup/performance-toolkit/profiles/ce/small.xml b/setup/performance-toolkit/profiles/ce/small.xml
index 4f9b436666f8c743c0fd0058c6fc747944506c9d..1949bb2a53f9aa69237b544ade511f4dd39815e0 100644
--- a/setup/performance-toolkit/profiles/ce/small.xml
+++ b/setup/performance-toolkit/profiles/ce/small.xml
@@ -68,8 +68,8 @@
                 <set_scheduled>false</set_scheduled>
             </indexer>
         </indexers>
-        <xi:include href="searchTerms.xml" />
-        <xi:include href="searchConfig.xml" />
-        <xi:include href="attributeSets.xml" />
+        <xi:include href="../../config/searchTerms.xml" />
+        <xi:include href="../../config/searchConfig.xml" />
+        <xi:include href="../../config/attributeSets.xml" />
     </profile>
 </config>
diff --git a/setup/src/Magento/Setup/Fixtures/FixtureModel.php b/setup/src/Magento/Setup/Fixtures/FixtureModel.php
index 44173a32c3e771ec2c43480a73c380ad2a2691ab..997244f5508933d05ae731255b81779f2528a101 100644
--- a/setup/src/Magento/Setup/Fixtures/FixtureModel.php
+++ b/setup/src/Magento/Setup/Fixtures/FixtureModel.php
@@ -221,6 +221,12 @@ class FixtureModel
      */
     public function getValue($key, $default = null)
     {
-        return isset($this->config['config']['profile'][$key]) ? $this->config['config']['profile'][$key] : $default;
+        return isset($this->config['config']['profile'][$key]) ?
+            (
+                // Work around for how attributes are handled in the XML parser when injected via xinclude due to the
+                // files existing outside of the current working directory.
+                isset($this->config['config']['profile'][$key]['_value']) ?
+                    $this->config['config']['profile'][$key]['_value'] : $this->config['config']['profile'][$key]
+            ) : $default;
     }
 }