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/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/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/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/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/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/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/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/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/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/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/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/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/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/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;
     }
 }