diff --git a/app/code/Magento/Catalog/Model/Category/Attribute/Source/Page.php b/app/code/Magento/Catalog/Model/Category/Attribute/Source/Page.php
index a62537b88cc8707f2de132e3063d4a0bc3140b74..3cff2cc0941a3b7b0ee6febfa0c6fc4ebb3ca88b 100644
--- a/app/code/Magento/Catalog/Model/Category/Attribute/Source/Page.php
+++ b/app/code/Magento/Catalog/Model/Category/Attribute/Source/Page.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Catalog\Model\Category\Attribute\Source;
 
-use Magento\Cms\Model\Resource\Block\Grid\CollectionFactory;
+use Magento\Cms\Model\Resource\Block\CollectionFactory;
 
 /**
  * Catalog category landing page attribute source
diff --git a/app/code/Magento/Catalog/Model/Resource/Category/Attribute/Source/Page.php b/app/code/Magento/Catalog/Model/Resource/Category/Attribute/Source/Page.php
index 10c44850e0f7c4e3ceda09b1fabee2f8fe564651..6e6b4406d71d4ac4d6d1fcd8f71a97bd32b8f0b7 100644
--- a/app/code/Magento/Catalog/Model/Resource/Category/Attribute/Source/Page.php
+++ b/app/code/Magento/Catalog/Model/Resource/Category/Attribute/Source/Page.php
@@ -15,16 +15,16 @@ class Page extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
     /**
      * Block collection factory
      *
-     * @var \Magento\Cms\Model\Resource\Block\Grid\CollectionFactory
+     * @var \Magento\Cms\Model\Resource\Block\CollectionFactory
      */
     protected $_blockCollectionFactory;
 
     /**
      * Construct
      *
-     * @param \Magento\Cms\Model\Resource\Block\Grid\CollectionFactory $blockCollectionFactory
+     * @param \Magento\Cms\Model\Resource\Block\CollectionFactory $blockCollectionFactory
      */
-    public function __construct(\Magento\Cms\Model\Resource\Block\Grid\CollectionFactory $blockCollectionFactory)
+    public function __construct(\Magento\Cms\Model\Resource\Block\CollectionFactory $blockCollectionFactory)
     {
         $this->_blockCollectionFactory = $blockCollectionFactory;
     }
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Category/Attribute/Source/PageTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Category/Attribute/Source/PageTest.php
index b55a39bce8812111d551e0833f73aa4adab27485..1086b9a0c28a189006cc0f248931ffc26c45917f 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Category/Attribute/Source/PageTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Category/Attribute/Source/PageTest.php
@@ -45,7 +45,7 @@ class PageTest extends \PHPUnit_Framework_TestCase
     {
         $mockedCollection = $this->getMockedCollection();
 
-        $mockBuilder = $this->getMockBuilder('Magento\Cms\Model\Resource\Block\Grid\CollectionFactory');
+        $mockBuilder = $this->getMockBuilder('Magento\Cms\Model\Resource\Block\CollectionFactory');
         $mock = $mockBuilder->setMethods(['create'])
             ->disableOriginalConstructor()
             ->getMock();
diff --git a/app/code/Magento/Checkout/Block/Cart/Sidebar.php b/app/code/Magento/Checkout/Block/Cart/Sidebar.php
index a811d6069b6ffe4a1f7469064bb79a7581fe8f87..549b8c8a54437223408fc59daebc1a78637fc0f6 100644
--- a/app/code/Magento/Checkout/Block/Cart/Sidebar.php
+++ b/app/code/Magento/Checkout/Block/Cart/Sidebar.php
@@ -9,6 +9,7 @@
 namespace Magento\Checkout\Block\Cart;
 
 use Magento\Framework\View\Block\IdentityInterface;
+use Magento\Store\Model\ScopeInterface;
 
 /**
  * Wishlist sidebar block
@@ -19,6 +20,7 @@ class Sidebar extends AbstractCart implements IdentityInterface
      * Xml pah to chackout sidebar count value
      */
     const XML_PATH_CHECKOUT_SIDEBAR_COUNT = 'checkout/sidebar/count';
+    const XML_PATH_CHECKOUT_SIDEBAR_DISPLAY = 'checkout/sidebar/display';
 
     /**
      * @var \Magento\Catalog\Model\Resource\Url
@@ -73,7 +75,7 @@ class Sidebar extends AbstractCart implements IdentityInterface
         if (is_null($count)) {
             $count = $this->_scopeConfig->getValue(
                 self::XML_PATH_CHECKOUT_SIDEBAR_COUNT,
-                \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+                ScopeInterface::SCOPE_STORE
             );
             $this->setData('item_count', $count);
         }
@@ -161,14 +163,43 @@ class Sidebar extends AbstractCart implements IdentityInterface
     /**
      * Get one page checkout page url
      *
-     * @return bool
-     * @SuppressWarnings(PHPMD.BooleanGetMethodName)
+     * @return string
      */
     public function getCheckoutUrl()
     {
         return $this->getUrl('checkout/onepage');
     }
 
+    /**
+     * Get shoppinc cart page url
+     *
+     * @return string
+     */
+    public function getShoppingCartUrl()
+    {
+        return $this->getUrl('checkout/cart');
+    }
+
+    /**
+     * Get update cart item url
+     *
+     * @return string
+     */
+    public function getUpdateItemQtyUrl()
+    {
+        return $this->getUrl('checkout/sidebar/updateItemQty');
+    }
+
+    /**
+     * Get remove cart item url
+     *
+     * @return string
+     */
+    public function getRemoveItemUrl()
+    {
+        return $this->getUrl('checkout/sidebar/removeItem');
+    }
+
     /**
      * Define if Mini Shopping Cart Pop-Up Menu enabled
      *
@@ -178,8 +209,8 @@ class Sidebar extends AbstractCart implements IdentityInterface
     public function getIsNeedToDisplaySideBar()
     {
         return (bool)$this->_scopeConfig->getValue(
-            'checkout/sidebar/display',
-            \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+            self::XML_PATH_CHECKOUT_SIDEBAR_DISPLAY,
+            ScopeInterface::SCOPE_STORE
         );
     }
 
@@ -284,8 +315,24 @@ class Sidebar extends AbstractCart implements IdentityInterface
         return $identities;
     }
 
+    /**
+     * Retrieve subtotal block html
+     *
+     * @return string
+     */
     public function getTotalsHtml()
     {
         return $this->getLayout()->getBlock('checkout.cart.minicart.totals')->toHtml();
     }
+
+    /**
+     * Retrieve items qty text
+     *
+     * @param int $qty
+     * @return \Magento\Framework\Phrase
+     */
+    public function getSummaryText($qty)
+    {
+        return ($qty == 1) ? __(' item') : __(' items');
+    }
 }
diff --git a/app/code/Magento/Checkout/Controller/Sidebar/RemoveItem.php b/app/code/Magento/Checkout/Controller/Sidebar/RemoveItem.php
new file mode 100644
index 0000000000000000000000000000000000000000..d0ed1515f90475a09ce1034632bd4db6c656267e
--- /dev/null
+++ b/app/code/Magento/Checkout/Controller/Sidebar/RemoveItem.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Controller\Sidebar;
+
+use Magento\Checkout\Model\Sidebar;
+use Magento\Framework\App\Action\Action;
+use Magento\Framework\App\Action\Context;
+use Magento\Framework\App\Response\Http;
+use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Json\Helper\Data;
+use Magento\Framework\View\Result\PageFactory;
+use Psr\Log\LoggerInterface;
+
+class RemoveItem extends Action
+{
+    /**
+     * @var Sidebar
+     */
+    protected $sidebar;
+
+    /**
+     * @var LoggerInterface
+     */
+    protected $logger;
+
+    /**
+     * @var Data
+     */
+    protected $jsonHelper;
+
+    /**
+     * @var PageFactory
+     */
+    protected $resultPageFactory;
+
+    /**
+     * @param Context $context
+     * @param Sidebar $sidebar
+     * @param LoggerInterface $logger
+     * @param Data $jsonHelper
+     * @param PageFactory $resultPageFactory
+     */
+    public function __construct(
+        Context $context,
+        Sidebar $sidebar,
+        LoggerInterface $logger,
+        Data $jsonHelper,
+        PageFactory $resultPageFactory
+    ) {
+        $this->sidebar = $sidebar;
+        $this->logger = $logger;
+        $this->jsonHelper = $jsonHelper;
+        $this->resultPageFactory = $resultPageFactory;
+        parent::__construct($context);
+    }
+
+    /**
+     * @return $this
+     */
+    public function execute()
+    {
+        $itemId = (int)$this->getRequest()->getParam('item_id');
+        try {
+            $this->sidebar->checkQuoteItem($itemId);
+            $this->sidebar->removeQuoteItem($itemId);
+            return $this->jsonResponse();
+        } catch (LocalizedException $e) {
+            return $this->jsonResponse($e->getMessage());
+        } catch (\Exception $e) {
+            $this->logger->critical($e);
+            return $this->jsonResponse($e->getMessage());
+        }
+    }
+
+    /**
+     * Compile JSON response
+     *
+     * @param string $error
+     * @return Http
+     */
+    protected function jsonResponse($error = '')
+    {
+        $response = $this->sidebar->getResponseData($error);
+
+        if (empty($error)) {
+            $resultPage = $this->resultPageFactory->create();
+            $block = $resultPage->getLayout()->getBlock('minicart.content')->toHtml();
+            $response['content'] = $block;
+        }
+
+        return $this->getResponse()->representJson(
+            $this->jsonHelper->jsonEncode($response)
+        );
+    }
+}
diff --git a/app/code/Magento/Checkout/Controller/Sidebar/UpdateItemQty.php b/app/code/Magento/Checkout/Controller/Sidebar/UpdateItemQty.php
new file mode 100644
index 0000000000000000000000000000000000000000..656ea11ad773b9a2141a12e4c6714ccc33a880f9
--- /dev/null
+++ b/app/code/Magento/Checkout/Controller/Sidebar/UpdateItemQty.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Controller\Sidebar;
+
+use Magento\Checkout\Model\Sidebar;
+use Magento\Framework\App\Action\Action;
+use Magento\Framework\App\Action\Context;
+use Magento\Framework\App\Response\Http;
+use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Json\Helper\Data;
+use Psr\Log\LoggerInterface;
+
+class UpdateItemQty extends Action
+{
+    /**
+     * @var Sidebar
+     */
+    protected $sidebar;
+
+    /**
+     * @var LoggerInterface
+     */
+    protected $logger;
+
+    /**
+     * @var Data
+     */
+    protected $jsonHelper;
+
+    /**
+     * @param Context $context
+     * @param Sidebar $sidebar
+     * @param LoggerInterface $logger
+     * @param Data $jsonHelper
+     */
+    public function __construct(
+        Context $context,
+        Sidebar $sidebar,
+        LoggerInterface $logger,
+        Data $jsonHelper
+    ) {
+        $this->sidebar = $sidebar;
+        $this->logger = $logger;
+        $this->jsonHelper = $jsonHelper;
+        parent::__construct($context);
+    }
+
+    /**
+     * @return $this
+     */
+    public function execute()
+    {
+        $itemId = (int)$this->getRequest()->getParam('item_id');
+        $itemQty = (int)$this->getRequest()->getParam('item_qty');
+
+        try {
+            $this->sidebar->checkQuoteItem($itemId);
+            $this->sidebar->updateQuoteItem($itemId, $itemQty);
+            return $this->jsonResponse();
+        } catch (LocalizedException $e) {
+            return $this->jsonResponse($e->getMessage());
+        } catch (\Exception $e) {
+            $this->logger->critical($e);
+            return $this->jsonResponse($e->getMessage());
+        }
+    }
+
+    /**
+     * Compile JSON response
+     *
+     * @param string $error
+     * @return Http
+     */
+    protected function jsonResponse($error = '')
+    {
+        return $this->getResponse()->representJson(
+            $this->jsonHelper->jsonEncode($this->sidebar->getResponseData($error))
+        );
+    }
+}
diff --git a/app/code/Magento/Checkout/Model/Cart.php b/app/code/Magento/Checkout/Model/Cart.php
index 898bbefe8c47fdcefa1bbe22e8599fbc72f224df..b023e8eda142fc9c3cefededf0b1ea027a308a3c 100644
--- a/app/code/Magento/Checkout/Model/Cart.php
+++ b/app/code/Magento/Checkout/Model/Cart.php
@@ -228,8 +228,10 @@ class Cart extends Object implements CartInterface
     {
         $quote = $this->getQuote()->setCheckoutMethod('');
         $this->_checkoutSession->setCartWasUpdated(true);
+        // TODO: Move this logic to Multishipping module as plug-in.
         // reset for multiple address checkout
-        if ($this->_checkoutSession->getCheckoutState() !== Session::CHECKOUT_STATE_BEGIN) {
+        if ($this->_checkoutSession->getCheckoutState() !== Session::CHECKOUT_STATE_BEGIN
+            && $this->_checkoutSession->getCheckoutState() !== null) {
             $quote->removeAllAddresses()->removePayment();
             $this->_checkoutSession->resetCheckout();
         }
diff --git a/app/code/Magento/Checkout/Model/Sidebar.php b/app/code/Magento/Checkout/Model/Sidebar.php
new file mode 100644
index 0000000000000000000000000000000000000000..225c5c7323bc48cc3d06f970acfa59b5a99d6965
--- /dev/null
+++ b/app/code/Magento/Checkout/Model/Sidebar.php
@@ -0,0 +1,178 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Model;
+
+use Magento\Checkout\Helper\Data as HelperData;
+use Magento\Checkout\Model\Cart;
+use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Locale\ResolverInterface;
+use Magento\Quote\Api\Data\CartItemInterface;
+use Magento\Quote\Model\Quote\Address\Total;
+
+class Sidebar
+{
+    /**
+     * @var Cart
+     */
+    protected $cart;
+
+    /**
+     * @var HelperData
+     */
+    protected $helperData;
+
+    /**
+     * @var ResolverInterface
+     */
+    protected $resolver;
+
+    /**
+     * @var int
+     */
+    protected $summaryQty;
+
+    /**
+     * @param Cart $cart
+     * @param HelperData $helperData
+     * @param ResolverInterface $resolver
+     */
+    public function __construct(
+        Cart $cart,
+        HelperData $helperData,
+        ResolverInterface $resolver
+    ) {
+        $this->cart = $cart;
+        $this->helperData = $helperData;
+        $this->resolver = $resolver;
+    }
+
+    /**
+     * Compile response data
+     *
+     * @param string $error
+     * @return array
+     */
+    public function getResponseData($error = '')
+    {
+        if (empty($error)) {
+            $response = [
+                'success' => true,
+                'data' => [
+                    'summary_qty' => $this->getSummaryQty(),
+                    'summary_text' => $this->getSummaryText(),
+                    'subtotal' => $this->getSubtotalHtml(),
+                ],
+            ];
+            if (!$this->getSummaryQty()) {
+                $response['cleanup'] = true;
+            }
+        } else {
+            $response = [
+                'success' => false,
+                'error_message' => $error,
+            ];
+        }
+        return $response;
+    }
+
+    /**
+     * Check if required quote item exist
+     *
+     * @param int $itemId
+     * @throws LocalizedException
+     * @return $this
+     */
+    public function checkQuoteItem($itemId)
+    {
+        $item = $this->cart->getQuote()->getItemById($itemId);
+        if (!$item instanceof CartItemInterface) {
+            throw new LocalizedException(__('We can\'t find the quote item.'));
+        }
+        return $this;
+    }
+
+    /**
+     * Remove quote item
+     *
+     * @param int $itemId
+     * @return $this
+     */
+    public function removeQuoteItem($itemId)
+    {
+        $this->cart->removeItem($itemId);
+        $this->cart->save();
+        return $this;
+    }
+
+    /**
+     * Update quote item
+     *
+     * @param int $itemId
+     * @param int $itemQty
+     * @throws LocalizedException
+     * @return $this
+     */
+    public function updateQuoteItem($itemId, $itemQty)
+    {
+        $itemData = [$itemId => ['qty' => $this->normalize($itemQty)]];
+        $this->cart->updateItems($itemData)->save();
+        return $this;
+    }
+
+    /**
+     * Apply normalization filter to item qty value
+     *
+     * @param int $itemQty
+     * @return int|array
+     */
+    protected function normalize($itemQty)
+    {
+        if ($itemQty) {
+            $filter = new \Zend_Filter_LocalizedToNormalized(
+                ['locale' => $this->resolver->getLocale()]
+            );
+            return $filter->filter($itemQty);
+        }
+        return $itemQty;
+    }
+
+    /**
+     * Retrieve summary qty
+     *
+     * @return int
+     */
+    protected function getSummaryQty()
+    {
+        if (!$this->summaryQty) {
+            $this->summaryQty = $this->cart->getSummaryQty();
+        }
+        return $this->summaryQty;
+    }
+
+    /**
+     * Retrieve summary qty text
+     *
+     * @return string
+     */
+    protected function getSummaryText()
+    {
+        return ($this->getSummaryQty() == 1) ? __(' item') : __(' items');
+    }
+
+    /**
+     * Retrieve subtotal block html
+     *
+     * @return string
+     */
+    protected function getSubtotalHtml()
+    {
+        $totals = $this->cart->getQuote()->getTotals();
+        $subtotal = isset($totals['subtotal']) && $totals['subtotal'] instanceof Total
+            ? $totals['subtotal']->getValue()
+            : 0;
+        return $this->helperData->formatPrice($subtotal);
+    }
+}
diff --git a/app/code/Magento/Checkout/Test/Unit/Controller/Sidebar/RemoveItemTest.php b/app/code/Magento/Checkout/Test/Unit/Controller/Sidebar/RemoveItemTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..900693acec908f43bb86e24f10f89e0d04585bb4
--- /dev/null
+++ b/app/code/Magento/Checkout/Test/Unit/Controller/Sidebar/RemoveItemTest.php
@@ -0,0 +1,234 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Test\Unit\Controller\Sidebar;
+
+use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+
+class RemoveItemTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Checkout\Controller\Sidebar\RemoveItem */
+    protected $removeItem;
+
+    /** @var ObjectManagerHelper */
+    protected $objectManagerHelper;
+
+    /** @var \Magento\Checkout\Model\Sidebar|\PHPUnit_Framework_MockObject_MockObject */
+    protected $sidebarMock;
+
+    /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $loggerMock;
+
+    /** @var \Magento\Framework\Json\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */
+    protected $jsonHelperMock;
+
+    /** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $requestMock;
+
+    /** @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $responseMock;
+
+    /** @var \Magento\Framework\View\Result\PageFactory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $resultPageFactoryMock;
+
+    protected function setUp()
+    {
+        $this->sidebarMock = $this->getMock('Magento\Checkout\Model\Sidebar', [], [], '', false);
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
+        $this->jsonHelperMock = $this->getMock('Magento\Framework\Json\Helper\Data', [], [], '', false);
+        $this->requestMock = $this->getMock('Magento\Framework\App\RequestInterface');
+        $this->responseMock = $this->getMockForAbstractClass(
+            'Magento\Framework\App\ResponseInterface',
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['representJson']
+        );
+        $this->resultPageFactoryMock = $this->getMock('Magento\Framework\View\Result\PageFactory', [], [], '', false);
+
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->removeItem = $this->objectManagerHelper->getObject(
+            'Magento\Checkout\Controller\Sidebar\RemoveItem',
+            [
+                'sidebar' => $this->sidebarMock,
+                'logger' => $this->loggerMock,
+                'jsonHelper' => $this->jsonHelperMock,
+                'request' => $this->requestMock,
+                'response' => $this->responseMock,
+                'resultPageFactory' => $this->resultPageFactoryMock,
+            ]
+        );
+    }
+
+    public function testExecute()
+    {
+        $this->requestMock->expects($this->once())
+            ->method('getParam')
+            ->with('item_id', null)
+            ->willReturn('1');
+
+        $this->sidebarMock->expects($this->once())
+            ->method('checkQuoteItem')
+            ->with(1)
+            ->willReturnSelf();
+        $this->sidebarMock->expects($this->once())
+            ->method('removeQuoteItem')
+            ->with(1)
+            ->willReturnSelf();
+        $this->sidebarMock->expects($this->once())
+            ->method('getResponseData')
+            ->with('')
+            ->willReturn(
+                [
+                    'cleanup' => true,
+                    'data' => [
+                        'summary_qty' => 0,
+                        'summary_text' => __(' items'),
+                        'subtotal' => 0,
+                    ],
+                ]
+            );
+
+        $pageMock = $this->getMockBuilder('Magento\Framework\View\Result\Page')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->resultPageFactoryMock->expects($this->once())
+            ->method('create')
+            ->with(false, [])
+            ->willReturn($pageMock);
+
+        $layoutMock = $this->getMockBuilder('Magento\Framework\View\LayoutInterface')
+            ->getMock();
+
+        $pageMock->expects($this->once())
+            ->method('getLayout')
+            ->willReturn($layoutMock);
+
+        $blockMock = $this->getMockBuilder('Magento\Framework\View\Element\BlockInterface')
+            ->getMock();
+
+        $layoutMock->expects($this->once())
+            ->method('getBlock')
+            ->with('minicart.content')
+            ->willReturn($blockMock);
+
+        $blockMock->expects($this->once())
+            ->method('toHtml')
+            ->willReturn('block html');
+
+        $this->jsonHelperMock->expects($this->once())
+            ->method('jsonEncode')
+            ->with(
+                [
+                    'cleanup' => true,
+                    'data' => [
+                        'summary_qty' => 0,
+                        'summary_text' => __(' items'),
+                        'subtotal' => 0,
+                    ],
+                    'content' => 'block html',
+                ]
+            )
+            ->willReturn('json encoded');
+
+        $this->responseMock->expects($this->once())
+            ->method('representJson')
+            ->with('json encoded')
+            ->willReturn('json represented');
+
+        $this->assertEquals('json represented', $this->removeItem->execute());
+    }
+
+    public function testExecuteWithLocalizedException()
+    {
+        $this->requestMock->expects($this->once())
+            ->method('getParam')
+            ->with('item_id', null)
+            ->willReturn('1');
+
+        $this->sidebarMock->expects($this->once())
+            ->method('checkQuoteItem')
+            ->with(1)
+            ->willThrowException(new LocalizedException(__('Error message!')));
+
+        $this->sidebarMock->expects($this->once())
+            ->method('getResponseData')
+            ->with('Error message!')
+            ->willReturn(
+                [
+                    'success' => false,
+                    'error_message' => 'Error message!',
+                ]
+            );
+
+        $this->jsonHelperMock->expects($this->once())
+            ->method('jsonEncode')
+            ->with(
+                [
+                    'success' => false,
+                    'error_message' => 'Error message!',
+                ]
+            )
+            ->willReturn('json encoded');
+
+        $this->responseMock->expects($this->once())
+            ->method('representJson')
+            ->with('json encoded')
+            ->willReturn('json represented');
+
+        $this->assertEquals('json represented', $this->removeItem->execute());
+    }
+
+    public function testExecuteWithException()
+    {
+        $this->requestMock->expects($this->once())
+            ->method('getParam')
+            ->with('item_id', null)
+            ->willReturn('1');
+
+        $exception = new \Exception('Error message!');
+
+        $this->sidebarMock->expects($this->once())
+            ->method('checkQuoteItem')
+            ->with(1)
+            ->willThrowException($exception);
+
+        $this->loggerMock->expects($this->once())
+            ->method('critical')
+            ->with($exception)
+            ->willReturn(null);
+
+        $this->sidebarMock->expects($this->once())
+            ->method('getResponseData')
+            ->with('Error message!')
+            ->willReturn(
+                [
+                    'success' => false,
+                    'error_message' => 'Error message!',
+                ]
+            );
+
+        $this->jsonHelperMock->expects($this->once())
+            ->method('jsonEncode')
+            ->with(
+                [
+                    'success' => false,
+                    'error_message' => 'Error message!',
+                ]
+            )
+            ->willReturn('json encoded');
+
+        $this->responseMock->expects($this->once())
+            ->method('representJson')
+            ->with('json encoded')
+            ->willReturn('json represented');
+
+        $this->assertEquals('json represented', $this->removeItem->execute());
+    }
+}
diff --git a/app/code/Magento/Checkout/Test/Unit/Controller/Sidebar/UpdateItemQtyTest.php b/app/code/Magento/Checkout/Test/Unit/Controller/Sidebar/UpdateItemQtyTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b36cbed010b0298348affe01da90822694fd8cb0
--- /dev/null
+++ b/app/code/Magento/Checkout/Test/Unit/Controller/Sidebar/UpdateItemQtyTest.php
@@ -0,0 +1,210 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Test\Unit\Controller\Sidebar;
+
+use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+
+class UpdateItemQtyTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Checkout\Controller\Sidebar\UpdateItemQty */
+    protected $updateItemQty;
+
+    /** @var ObjectManagerHelper */
+    protected $objectManagerHelper;
+
+    /** @var \Magento\Checkout\Model\Sidebar|\PHPUnit_Framework_MockObject_MockObject */
+    protected $sidebarMock;
+
+    /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $loggerMock;
+
+    /** @var \Magento\Framework\Json\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */
+    protected $jsonHelperMock;
+
+    /** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $requestMock;
+
+    /** @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $responseMock;
+
+    protected function setUp()
+    {
+        $this->sidebarMock = $this->getMock('Magento\Checkout\Model\Sidebar', [], [], '', false);
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
+        $this->jsonHelperMock = $this->getMock('Magento\Framework\Json\Helper\Data', [], [], '', false);
+        $this->requestMock = $this->getMock('Magento\Framework\App\RequestInterface');
+        $this->responseMock = $this->getMockForAbstractClass(
+            'Magento\Framework\App\ResponseInterface',
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['representJson']
+        );
+
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->updateItemQty = $this->objectManagerHelper->getObject(
+            'Magento\Checkout\Controller\Sidebar\UpdateItemQty',
+            [
+                'sidebar' => $this->sidebarMock,
+                'logger' => $this->loggerMock,
+                'jsonHelper' => $this->jsonHelperMock,
+                'request' => $this->requestMock,
+                'response' => $this->responseMock,
+            ]
+        );
+    }
+
+    public function testExecute()
+    {
+        $this->requestMock->expects($this->at(0))
+            ->method('getParam')
+            ->with('item_id', null)
+            ->willReturn('1');
+        $this->requestMock->expects($this->at(1))
+            ->method('getParam')
+            ->with('item_qty', null)
+            ->willReturn('2');
+
+        $this->sidebarMock->expects($this->once())
+            ->method('checkQuoteItem')
+            ->with(1)
+            ->willReturnSelf();
+        $this->sidebarMock->expects($this->once())
+            ->method('updateQuoteItem')
+            ->with(1, 2)
+            ->willReturnSelf();
+        $this->sidebarMock->expects($this->once())
+            ->method('getResponseData')
+            ->with('')
+            ->willReturn(
+                [
+                    'data' => [
+                        'summary_qty' => 2,
+                        'summary_text' => __(' items'),
+                        'subtotal' => 12.34,
+                    ],
+                ]
+            );
+
+        $this->jsonHelperMock->expects($this->once())
+            ->method('jsonEncode')
+            ->with(
+                [
+                    'data' => [
+                        'summary_qty' => 2,
+                        'summary_text' => __(' items'),
+                        'subtotal' => 12.34,
+                    ],
+                ]
+            )
+            ->willReturn('json encoded');
+
+        $this->responseMock->expects($this->once())
+            ->method('representJson')
+            ->with('json encoded')
+            ->willReturn('json represented');
+
+        $this->assertEquals('json represented', $this->updateItemQty->execute());
+    }
+
+    public function testExecuteWithLocalizedException()
+    {
+        $this->requestMock->expects($this->at(0))
+            ->method('getParam')
+            ->with('item_id', null)
+            ->willReturn('1');
+        $this->requestMock->expects($this->at(1))
+            ->method('getParam')
+            ->with('item_qty', null)
+            ->willReturn('2');
+
+        $this->sidebarMock->expects($this->once())
+            ->method('checkQuoteItem')
+            ->with(1)
+            ->willThrowException(new LocalizedException(__('Error!')));
+
+        $this->sidebarMock->expects($this->once())
+            ->method('getResponseData')
+            ->with('Error!')
+            ->willReturn(
+                [
+                    'success' => false,
+                    'error_message' => 'Error!',
+                ]
+            );
+
+        $this->jsonHelperMock->expects($this->once())
+            ->method('jsonEncode')
+            ->with(
+                [
+                    'success' => false,
+                    'error_message' => 'Error!',
+                ]
+            )
+            ->willReturn('json encoded');
+
+        $this->responseMock->expects($this->once())
+            ->method('representJson')
+            ->with('json encoded')
+            ->willReturn('json represented');
+
+        $this->assertEquals('json represented', $this->updateItemQty->execute());
+    }
+
+    public function testExecuteWithException()
+    {
+        $this->requestMock->expects($this->at(0))
+            ->method('getParam')
+            ->with('item_id', null)
+            ->willReturn('1');
+        $this->requestMock->expects($this->at(1))
+            ->method('getParam')
+            ->with('item_qty', null)
+            ->willReturn('2');
+
+        $exception = new \Exception('Error!');
+
+        $this->sidebarMock->expects($this->once())
+            ->method('checkQuoteItem')
+            ->with(1)
+            ->willThrowException($exception);
+
+        $this->loggerMock->expects($this->once())
+            ->method('critical')
+            ->with($exception)
+            ->willReturn(null);
+
+        $this->sidebarMock->expects($this->once())
+            ->method('getResponseData')
+            ->with('Error!')
+            ->willReturn(
+                [
+                    'success' => false,
+                    'error_message' => 'Error!',
+                ]
+            );
+
+        $this->jsonHelperMock->expects($this->once())
+            ->method('jsonEncode')
+            ->with(
+                [
+                    'success' => false,
+                    'error_message' => 'Error!',
+                ]
+            )
+            ->willReturn('json encoded');
+
+        $this->responseMock->expects($this->once())
+            ->method('representJson')
+            ->with('json encoded')
+            ->willReturn('json represented');
+
+        $this->assertEquals('json represented', $this->updateItemQty->execute());
+    }
+}
diff --git a/app/code/Magento/Checkout/Test/Unit/Model/SidebarTest.php b/app/code/Magento/Checkout/Test/Unit/Model/SidebarTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c928db0923da844cdecd741b08269824d726a6f5
--- /dev/null
+++ b/app/code/Magento/Checkout/Test/Unit/Model/SidebarTest.php
@@ -0,0 +1,233 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Checkout\Test\Unit\Model;
+
+use Magento\Checkout\Model\Sidebar;
+
+class SidebarTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var Sidebar */
+    protected $sidebar;
+
+    /** @var \Magento\Checkout\Model\Cart|\PHPUnit_Framework_MockObject_MockObject */
+    protected $cartMock;
+
+    /** @var \Magento\Checkout\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */
+    protected $checkoutHelperMock;
+
+    /** @var \Magento\Framework\Locale\ResolverInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $resolverMock;
+
+    protected function setUp()
+    {
+        $this->cartMock = $this->getMock('Magento\Checkout\Model\Cart', [], [], '', false);
+        $this->checkoutHelperMock = $this->getMock('Magento\Checkout\Helper\Data', [], [], '', false);
+        $this->resolverMock = $this->getMock('Magento\Framework\Locale\ResolverInterface');
+
+        $this->sidebar = new Sidebar(
+            $this->cartMock,
+            $this->checkoutHelperMock,
+            $this->resolverMock
+        );
+    }
+
+    /**
+     * @param string $error
+     * @param float $summaryQty
+     * @param array $totals
+     * @param array $result
+     *
+     * @dataProvider dataProviderGetResponseData
+     */
+    public function testGetResponseData($error, $summaryQty, $totals, $result)
+    {
+        $quoteMock = $this->getMockBuilder('Magento\Quote\Model\Quote')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $quoteMock->expects($this->any())
+            ->method('getTotals')
+            ->willReturn($totals);
+
+        $this->cartMock->expects($this->any())
+            ->method('getSummaryQty')
+            ->willReturn($summaryQty);
+        $this->cartMock->expects($this->any())
+            ->method('getQuote')
+            ->willReturn($quoteMock);
+
+        $this->checkoutHelperMock->expects($this->any())
+            ->method('formatPrice')
+            ->willReturnArgument(0);
+
+        $this->assertEquals($result, $this->sidebar->getResponseData($error));
+    }
+
+    public function dataProviderGetResponseData()
+    {
+        $totalMock = $this->getMockBuilder('Magento\Quote\Model\Quote\Address\Total')
+            ->disableOriginalConstructor()
+            ->setMethods(['getValue'])
+            ->getMock();
+        $totalMock->expects($this->any())
+            ->method('getValue')
+            ->willReturn(12.34);
+
+        return [
+            [
+                '',
+                0,
+                [],
+                [
+                    'success' => true,
+                    'data' => [
+                        'summary_qty' => 0,
+                        'summary_text' => __(' items'),
+                        'subtotal' => 0,
+                    ],
+                    'cleanup' => true,
+                ],
+            ],
+            [
+                '',
+                1,
+                [
+                    'subtotal' => $this->getMock('NonexistentClass'),
+                ],
+                [
+                    'success' => true,
+                    'data' => [
+                        'summary_qty' => 1,
+                        'summary_text' => __(' item'),
+                        'subtotal' => 0,
+                    ],
+                ],
+            ],
+            [
+                '',
+                2,
+                [
+                    'subtotal' => $totalMock,
+                ],
+                [
+                    'success' => true,
+                    'data' => [
+                        'summary_qty' => 2,
+                        'summary_text' => __(' items'),
+                        'subtotal' => 12.34,
+                    ],
+                ],
+            ],
+            [
+                'Error',
+                0,
+                [],
+                [
+                    'success' => false,
+                    'error_message' => 'Error',
+                ],
+            ],
+        ];
+    }
+
+    public function testCheckQuoteItem()
+    {
+        $itemId = 1;
+
+        $itemMock = $this->getMockBuilder('Magento\Quote\Api\Data\CartItemInterface')
+            ->getMock();
+
+        $quoteMock = $this->getMockBuilder('Magento\Quote\Model\Quote')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $quoteMock->expects($this->once())
+            ->method('getItemById')
+            ->with($itemId)
+            ->willReturn($itemMock);
+
+        $this->cartMock->expects($this->any())
+            ->method('getQuote')
+            ->willReturn($quoteMock);
+
+        $this->assertEquals($this->sidebar, $this->sidebar->checkQuoteItem($itemId));
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @exceptedExceptionMessage We can't find the quote item.
+     */
+    public function testCheckQuoteItemWithException()
+    {
+        $itemId = 2;
+
+        $quoteMock = $this->getMockBuilder('Magento\Quote\Model\Quote')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $quoteMock->expects($this->once())
+            ->method('getItemById')
+            ->with($itemId)
+            ->willReturn(null);
+
+        $this->cartMock->expects($this->any())
+            ->method('getQuote')
+            ->willReturn($quoteMock);
+
+        $this->sidebar->checkQuoteItem($itemId);
+    }
+
+    public function testRemoveQuoteItem()
+    {
+        $itemId = 1;
+
+        $this->cartMock->expects($this->once())
+            ->method('removeItem')
+            ->with($itemId)
+            ->willReturnSelf();
+        $this->cartMock->expects($this->once())
+            ->method('save')
+            ->willReturnSelf();
+
+        $this->assertEquals($this->sidebar, $this->sidebar->removeQuoteItem($itemId));
+    }
+
+    public function testUpdateQuoteItem()
+    {
+        $itemId = 1;
+        $itemQty = 2;
+
+        $this->resolverMock->expects($this->once())
+            ->method('getLocale')
+            ->willReturn('en');
+
+        $this->cartMock->expects($this->once())
+            ->method('updateItems')
+            ->with([$itemId => ['qty' => $itemQty]])
+            ->willReturnSelf();
+        $this->cartMock->expects($this->once())
+            ->method('save')
+            ->willReturnSelf();
+
+        $this->assertEquals($this->sidebar, $this->sidebar->updateQuoteItem($itemId, $itemQty));
+    }
+
+    public function testUpdateQuoteItemWithZeroQty()
+    {
+        $itemId = 1;
+        $itemQty = 0;
+
+        $this->resolverMock->expects($this->never())
+            ->method('getLocale');
+
+        $this->cartMock->expects($this->once())
+            ->method('updateItems')
+            ->with([$itemId => ['qty' => $itemQty]])
+            ->willReturnSelf();
+        $this->cartMock->expects($this->once())
+            ->method('save')
+            ->willReturnSelf();
+
+        $this->assertEquals($this->sidebar, $this->sidebar->updateQuoteItem($itemId, $itemQty));
+    }
+}
diff --git a/app/code/Magento/Checkout/etc/config.xml b/app/code/Magento/Checkout/etc/config.xml
index 31f59f6d891c5af880e55ec5d2dda30c5d26ab28..060d51932d09facdc524faa5e64d3a4032df9d90 100644
--- a/app/code/Magento/Checkout/etc/config.xml
+++ b/app/code/Magento/Checkout/etc/config.xml
@@ -21,7 +21,7 @@
             </cart_link>
             <sidebar>
                 <display>1</display>
-                <count>3</count>
+                <count>5</count>
             </sidebar>
             <payment_failed>
                 <identity>general</identity>
diff --git a/app/code/Magento/Checkout/view/frontend/layout/default.xml b/app/code/Magento/Checkout/view/frontend/layout/default.xml
index e563c4b56bf96830d92fcfd9f85dbcfe36143630..8fff222718790f074ae8935ce68923e51010f134 100644
--- a/app/code/Magento/Checkout/view/frontend/layout/default.xml
+++ b/app/code/Magento/Checkout/view/frontend/layout/default.xml
@@ -15,14 +15,17 @@
         </referenceBlock>
         <referenceContainer name="header-wrapper">
             <block class="Magento\Checkout\Block\Cart\Sidebar" name="minicart" as="minicart" after="logo" template="cart/minicart.phtml">
-                <block class="Magento\Framework\View\Element\RendererList" name="checkout.cart.sidebar.item.renderers" as="renderer.list"/>
-                <container name="minicart.subtotal.container" as="subtotal" label="My Cart Subtotal">
-                    <block name="minicart.subtotal" class="Magento\Checkout\Block\Cart\Sidebar" template="cart/subtotal.phtml"/>
-                </container>
-                <container name="minicart.extra.info" as="minicart_info" label="My Cart Extra info"/>
-                <container name="topCart.extra_actions" as="extra_actions" label="My Cart Extra Actions">
-                    <block class="Magento\Catalog\Block\ShortcutButtons" name="topCart.shortcut.buttons"/>
-                </container>
+                <block class="Magento\Checkout\Block\Cart\Sidebar" name="minicart.content" as="minicart_content" template="cart/minicart/content.phtml">
+                    <block class="Magento\Framework\View\Element\RendererList" name="checkout.cart.sidebar.item.renderers" as="renderer.list"/>
+                    <container name="minicart.subtotal.container" as="subtotal" label="My Cart Subtotal">
+                        <block name="minicart.subtotal" class="Magento\Checkout\Block\Cart\Sidebar" template="cart/subtotal.phtml"/>
+                    </container>
+                    <container name="minicart.promotion" as="cart_promotion" label="Mini-cart promotion block"/>
+                    <container name="minicart.extra.info" as="minicart_info" label="My Cart Extra info"/>
+                    <container name="topCart.extra_actions" as="extra_actions" label="My Cart Extra Actions">
+                        <block class="Magento\Catalog\Block\ShortcutButtons" name="topCart.shortcut.buttons"/>
+                    </container>
+                </block>
             </block>
         </referenceContainer>
     </body>
diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml
index 355971348cbe9b8516d2f007cbda6da38b360d61..9082c7696e4e1217e5c38514bcf50f154bb7f8d4 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml
@@ -8,104 +8,71 @@
 
 /** @var $block \Magento\Checkout\Block\Cart\Sidebar */
 ?>
-<?php if ($block->getInList()): ?>
-    <li data-block="minicart" class="minicart-wrapper">
-<?php else:  ?>
-    <div data-block="minicart" class="minicart-wrapper">
-<?php endif; ?>
+
 <?php $_cartQty = (float) $block->getSummaryCount() ?>
-<?php if (!$block->getIsLinkMode() || !$block->getIsNeedToDisplaySideBar()): ?>
-    <a class="action showcart" href="<?php echo $block->getUrl('checkout/cart'); ?>">
+<div data-block="minicart" class="minicart-wrapper">
+    <a class="action showcart" href="<?php echo $block->getShoppingCartUrl(); ?>">
         <span class="text"><?php echo __('My Cart'); ?></span>
         <span class="counter qty<?php echo($_cartQty > 0) ? '' : ' empty'; ?>">
             <span class="counter-number">
                 <?php echo $_cartQty;?>
             </span>
             <span class="counter-label">
-                <?php if ($_cartQty == 1):?>
-                    <?php echo __('item');?>
-                <?php else:?>
-                    <?php echo __('items');?>
-                <?php endif;?>
+                <?php echo $block->getSummaryText($_cartQty); ?>
             </span>
         </span>
     </a>
     <?php if ($block->getIsNeedToDisplaySideBar()): ?>
-        <div class="block block-minicart<?php echo($_cartQty > 0) ? '' : ' empty'; ?>" <?php if ($block->getIsNeedToDisplaySideBar()): ?> data-mage-init='{"dropdownDialog":{"appendTo":"[data-block=minicart]", "triggerTarget":".showcart", "timeout": "2000", "triggerClass":"active", "parentClass":"active"}}'<?php endif ?>>
-            <div class="title">
-                <strong>
-                    <span class="text"><?php echo __('My Cart'); ?></span>
-                    <span title="<?php echo __('Items in Cart'); ?>"
-                          class="qty<?php echo($_cartQty > 0) ? '' : ' empty'; ?>"
-                        ><?php echo $_cartQty ?></span>
-                </strong>
-            </div>
-            <div class="content">
-                <?php if ($_cartQty || $block->getAllowCartLink()): ?>
-                    <div class="items-total">
-                        <?php echo($_cartQty == 1) ? __('1 item ') : __('%1 items ', $_cartQty) ?>
-                    </div>
-                    <?php $isPossibleOnepageCheckout = $_cartQty && $block->isPossibleOnepageCheckout() ?>
-                    <?php if ($isPossibleOnepageCheckout): ?>
-                        <?php echo $block->getChildHtml('subtotal'); ?>
-                    <?php endif; ?>
-                    <?php echo $block->getChildHtml('minicart_info') ?>
-                    <div class="actions">
-                        <div class="primary">
-                            <?php if ($isPossibleOnepageCheckout): ?>
-                                <button
-                                    id="top-cart-btn-checkout"
-                                    type="button"
-                                    class="action checkout primary"
-                                    title="<?php echo __('Go to Checkout') ?>">
-                                    <span><?php echo __('Go to Checkout') ?></span>
-                                </button>
-                                <?php echo $block->getChildHtml('extra_actions') ?>
-                            <?php endif; ?>
-                        </div>
-                        <div class="secondary">
-                            <a class="action viewcart" href="<?php echo $block->getUrl('checkout/cart'); ?>">
-                                <span><?php echo __('Go to Shopping Cart') ?></span>
-                            </a>
-                        </div>
-                    </div>
-                <?php endif ?>
-                <?php $_items = $block->getRecentItems() ?>
-                <?php if (count($_items)): ?>
-                    <strong class="subtitle"><?php echo __('Recently added item(s)') ?></strong>
-                    <div data-action="scroll" class="products minilist">
-                        <ol id="mini-cart" class="minilist items">
-                            <?php foreach ($_items as $_item): ?>
-                            <?php echo $block->getItemHtml($_item) ?>
-                            <?php endforeach; ?>
-                        </ol>
-                    </div>
-                <?php else: ?>
-                    <strong class="subtitle empty">
-                        <?php echo __('You have no items in your shopping cart.') ?>
-                    </strong>
-                    <?php if ($block->getCartEmptyMessage()): ?>
-                        <p class="minicart empty text"><?php echo $block->getCartEmptyMessage(); ?></p>
-                    <?php endif; ?>
-                <?php endif ?>
+        <div class="block block-minicart<?php echo($_cartQty > 0) ? '' : ' empty'; ?>"
+             data-mage-init='{"dropdownDialog":{
+                "appendTo":"[data-block=minicart]",
+                "triggerTarget":".showcart",
+                "timeout": "2000",
+                "closeOnMouseLeave": false,
+                "closeOnEscape": true,
+                "triggerClass":"active",
+                "parentClass":"active",
+                "buttons":[]}}'>
+            <div id="minicart-content-wrapper">
+                <?php echo $block->getChildHtml('minicart_content') ?>
             </div>
         </div>
     <?php endif ?>
-<?php endif; ?>
-<script type="text/x-magento-init">
+    <script type="text/x-magento-init">
     {
         "[data-block='minicart']": {
             "sidebar": {
-                "checkoutUrl": "<?php echo $block->getCheckoutUrl();?>",
-                "checkoutButton": "#top-cart-btn-checkout",
-                "removeButton": "#mini-cart a.action.delete",
+                "targetElement": "div.block.block-minicart",
+                "url": {
+                    "checkout": "<?php echo $block->getCheckoutUrl();?>",
+                    "update": "<?php echo $block->getUpdateItemQtyUrl(); ?>",
+                    "remove": "<?php echo $block->getRemoveItemUrl(); ?>"
+                },
+                "button": {
+                    "checkout": "#top-cart-btn-checkout",
+                    "remove": "#mini-cart a.action.delete",
+                    "close": "#btn-minicart-close"
+                },
+                "showcart": {
+                    "parent": "span.counter",
+                    "qty": "span.counter-number",
+                    "label": "span.counter-label"
+                },
+                "minicart": {
+                    "list": "#mini-cart",
+                    "content": "#minicart-content-wrapper",
+                    "qty": "div.items-total",
+                    "subtotal": "div.subtotal span.price"
+                },
+                "item": {
+                    "qty": ":input.cart-item-qty",
+                    "button": ":button.update-cart-item"
+                },
                 "confirmMessage": "<?php echo __('Are you sure you would like to remove this item from the shopping cart?') ?>"
             }
         }
     }
-</script>
-<?php if ($block->getInList()): ?>
-    </li>
-<?php else:  ?>
-    </div>
-<?php endif; ?>
+    </script>
+</div>
+
+
diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/minicart/content.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/minicart/content.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..ac59b9dce84a0ff7b5584db0b7a99e7d6fed28c3
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/templates/cart/minicart/content.phtml
@@ -0,0 +1,87 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+// @codingStandardsIgnoreFile
+
+/** @var $block \Magento\Checkout\Block\Cart\Sidebar */
+?>
+
+<?php $_cartQty = (float) $block->getSummaryCount() ?>
+<div class="block-title">
+    <strong>
+        <span class="text"><?php echo __('My Cart'); ?></span>
+                    <span title="<?php echo $block->escapeHtml(__('Items in Cart')); ?>"
+                          class="qty<?php echo($_cartQty > 0) ? '' : ' empty'; ?>"
+                        ><?php echo $_cartQty ?></span>
+    </strong>
+</div>
+<div class="block-content">
+    <button type="button"
+            id="btn-minicart-close"
+            title="<?php echo $block->escapeHtml(__('Close')); ?>"
+            class="action close">
+        <span><?php echo __('Close') ?></span>
+    </button>
+
+    <?php if ($_cartQty || $block->getAllowCartLink()): ?>
+        <div class="items-total">
+            <span class="count"><?php echo $_cartQty; ?></span>
+            <?php echo $block->getSummaryText($_cartQty); ?>
+        </div>
+        <?php $isPossibleOnepageCheckout = $_cartQty && $block->isPossibleOnepageCheckout() ?>
+        <?php if ($isPossibleOnepageCheckout): ?>
+            <?php echo $block->getChildHtml('subtotal'); ?>
+        <?php endif; ?>
+        <?php echo $block->getChildHtml('minicart_info') ?>
+        <div class="actions">
+            <div class="primary">
+                <?php if ($isPossibleOnepageCheckout): ?>
+                    <button
+                        id="top-cart-btn-checkout"
+                        type="button"
+                        class="action primary checkout"
+                        title="<?php echo $block->escapeHtml(__('Go to Checkout')); ?>">
+                        <span><?php echo __('Go to Checkout') ?></span>
+                    </button>
+                    <?php echo $block->getChildHtml('extra_actions') ?>
+                <?php endif; ?>
+            </div>
+        </div>
+    <?php endif ?>
+
+    <?php $_items = $block->getRecentItems() ?>
+    <?php if (count($_items)): ?>
+        <strong class="subtitle"><?php echo __('Recently added item(s)') ?></strong>
+        <div data-action="scroll" class="minicart-items-wrapper">
+            <ol id="mini-cart" class="minicart-items">
+                <?php foreach ($_items as $_item): ?>
+                    <?php echo $block->getItemHtml($_item) ?>
+                <?php endforeach; ?>
+            </ol>
+        </div>
+    <?php else: ?>
+        <strong class="subtitle empty">
+            <?php echo __('You have no items in your shopping cart.') ?>
+        </strong>
+        <?php if ($block->getCartEmptyMessage()): ?>
+            <p class="minicart empty text"><?php echo $block->getCartEmptyMessage(); ?></p>
+        <?php endif; ?>
+    <?php endif ?>
+
+    <?php if ($_cartQty || $block->getAllowCartLink()): ?>
+        <div class="actions">
+            <div class="secondary">
+                <a class="action viewcart" href="<?php echo $block->getUrl('checkout/cart'); ?>">
+                    <span><?php echo __('View and edit cart') ?></span>
+                </a>
+            </div>
+        </div>
+    <?php endif ?>
+
+    <div id="minicart-widgets" class="minicart-widgets">
+        <?php echo $block->getChildHtml('cart_promotion') ?>
+    </div>
+</div>
diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/sidebar/default.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/sidebar/default.phtml
index 826cc8efac19b814a976cca84a512d30b3c1a454..5a5d1cba87399286e052eab523e4c514cfc76ec7 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/cart/sidebar/default.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/cart/sidebar/default.phtml
@@ -75,9 +75,23 @@ $imageBlock = $block->getLayout()->createBlock('Magento\Catalog\Block\Product\Im
                     <?php echo $block->getSidebarItemPriceHtml($_item); ?>
                 <?php endif; //Can apply MSRP ?>
 
-                <div class="details-qty">
+                <div class="details-qty qty">
                     <span class="label"><?php echo __('Qty'); ?></span>
-                    <span class="value qty"><?php echo $block->getQty() ?></span>
+                    <input id="cart-item-<?php echo $_item->getId() ?>-qty"
+                           value="<?php echo $block->getQty() ?>"
+                           type="number"
+                           size="4"
+                           class="item-qty cart-item-qty"
+                           data-cart-item="<?php echo $_item->getId() ?>"
+                           data-item-qty="<?php echo $block->getQty() ?>"
+                           maxlength="12"/>
+                    <button id="update-cart-item-<?php echo $_item->getId() ?>"
+                            class="update-cart-item"
+                            data-cart-item="<?php echo $_item->getId() ?>"
+                            title="<?php echo $block->escapeHtml(__('Update')); ?>"
+                            style="display: none">
+                        <span><?php echo __('Update'); ?></span>
+                    </button>
                 </div>
             </div>
 
@@ -85,12 +99,17 @@ $imageBlock = $block->getLayout()->createBlock('Magento\Catalog\Block\Product\Im
                 <?php if ($product->isVisibleInSiteVisibility()):?>
                 <div class="primary">
                     <a href="<?php echo $block->getConfigureUrl() ?>"
-                       title="<?php echo __('Edit item') ?>"
-                       class="action edit"><span><?php echo __('Edit')?></span></a>
+                       title="<?php echo $block->escapeHtml(__('Edit item')); ?>"
+                       class="action edit">
+                       <span><?php echo __('Edit')?></span>
+                   </a>
                 </div>
                 <?php endif ?>
                 <div class="secondary">
-                    <a href="#" data-post='<?php echo $this->helper('Magento\Checkout\Helper\Cart')->getDeletePostJson($_item); ?>' title="<?php echo __('Remove item') ?>" class="action delete">
+                    <a href="#"
+                       data-cart-item="<?php echo $_item->getId() ?>"
+                       title="<?php echo $block->escapeHtml(__('Remove item')); ?>"
+                       class="action delete">
                         <span><?php echo __('Remove')?></span>
                     </a>
                 </div>
diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/subtotal.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/subtotal.phtml
index 34e8b3922671cebd25915227a7e2459532045246..291a8a762fe899ffeb9726aa6d2ab8043fad0339 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/cart/subtotal.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/cart/subtotal.phtml
@@ -6,7 +6,7 @@
 /** @var $block \Magento\Checkout\Block\Cart\Sidebar */
 ?>
 <div class="subtotal">
-    <span class="mark">
+    <span class="label">
         <?php echo __('Cart Subtotal') ?>
     </span>
     <?php echo $block->getTotalsHtml() ?>
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js b/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js
index 59e5f2e35d81022aa4bef3e624713d5d8ff91396..d3c3a264b88d814fd8123aa84bc1df10d3828aa6 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js
@@ -12,18 +12,242 @@ define([
 
     $.widget('mage.sidebar', {
         options: {
-            isRecursive: true
+            isRecursive: true,
+            maxItemsVisible: 3
         },
+        scrollHeight: 0,
+
         _create: function() {
+            this._initContent();
+        },
+
+        _initContent: function() {
+            var self = this;
+
             this.element.decorate('list', this.options.isRecursive);
-            $(this.options.checkoutButton).on('click', $.proxy(function() {
-                location.href = this.options.checkoutUrl;
-            }, this));
-            $(this.options.removeButton).on('click', $.proxy(function() {
-                return confirm(this.options.confirmMessage);
+
+            $(this.options.button.close).click(function(event) {
+                event.stopPropagation();
+                $(self.options.targetElement).dropdownDialog("close");
+            });
+
+            $(this.options.button.checkout).on('click', $.proxy(function() {
+                location.href = this.options.url.checkout;
             }, this));
+
+            $(this.options.button.remove).click(function(event) {
+                event.stopPropagation();
+                if (confirm(self.options.confirmMessage)) {
+                    self._removeItem($(this));
+                }
+            });
+
+            $(this.options.item.qty).keyup(function() {
+                self._showItemButton($(this));
+            });
+            $(this.options.item.button).click(function(event) {
+                event.stopPropagation();
+                self._updateItemQty($(this))
+            });
+
+            this._calcHeight();
+            this._isOverflowed();
+        },
+
+        /**
+         * Add 'overflowed' class to minicart items wrapper element
+         *
+         * @private
+         */
+        _isOverflowed: function() {
+            var list = $(this.options.minicart.list);
+            if (this.scrollHeight > list.innerHeight()) {
+                list.parent().addClass('overflowed');
+            } else {
+                list.parent().removeClass('overflowed');
+            }
+        },
+
+        _showItemButton: function(elem) {
+            var itemId = elem.data('cart-item');
+            var itemQty = elem.data('item-qty');
+            if (this._isValidQty(itemQty, elem.val())) {
+                $('#update-cart-item-' + itemId).show('fade', 300);
+            } else if (elem.val() == 0) {
+                elem.val(itemQty);
+                this._hideItemButton(elem);
+            } else {
+                this._hideItemButton(elem);
+            }
+        },
+
+        /**
+         * @param origin - origin qty. 'data-item-qty' attribute.
+         * @param changed - new qty.
+         * @returns {boolean}
+         * @private
+         */
+        _isValidQty: function(origin, changed) {
+            return (origin != changed)
+                && (changed.length > 0)
+                && (changed - 0 == changed)
+                && (changed - 0 > 0);
+        },
+
+        _hideItemButton: function(elem) {
+            var itemId = elem.data('cart-item');
+            $('#update-cart-item-' + itemId).hide('fade', 300);
+        },
+
+        _updateItemQty: function(elem) {
+            var itemId = elem.data('cart-item');
+            this._ajax(this.options.url.update, {
+                item_id: itemId,
+                item_qty: $('#cart-item-' + itemId + '-qty').val()
+            }, elem, this._updateItemQtyAfter);
+        },
+
+        /**
+         * Update content after update qty
+         *
+         * @param elem
+         * @param response
+         * @private
+         */
+        _updateItemQtyAfter: function(elem, response) {
+            if ($.type(response.data) === 'object') {
+                this._refreshQty(response.data.summary_qty, response.data.summary_text);
+                this._refreshSubtotal(response.data.subtotal);
+                this._refreshShowcart(response.data.summary_qty, response.data.summary_text);
+                this._refreshItemQty(elem, response.data.summary_qty);
+            }
+            this._hideItemButton(elem);
+        },
+
+        _removeItem: function(elem) {
+            var itemId = elem.data('cart-item');
+            this._ajax(this.options.url.remove, {
+                item_id: itemId
+            }, elem, this._removeItemAfter);
+        },
+
+        /**
+         * Update content after item remove
+         *
+         * @param elem
+         * @param response
+         * @private
+         */
+        _removeItemAfter: function(elem, response) {
+            if ($.type(response.data) === 'object') {
+                this._refreshShowcart(response.data.summary_qty, response.data.summary_text);
+            }
+            $(this.options.minicart.content).html($.trim(response.content));
+            if (response.cleanup === true) {
+                $(this.options.showcart.parent).addClass('empty');
+            }
+            this._initContent();
+        },
+
+        /**
+         * @param url - ajax url
+         * @param data - post data for ajax call
+         * @param elem - element that initiated the event
+         * @param callback - callback method to execute after AJAX success
+         */
+        _ajax: function(url, data, elem, callback) {
+            $.ajax({
+                url: url,
+                data: data,
+                type: 'post',
+                dataType: 'json',
+                context: this,
+                beforeSend: function() {
+                    elem.attr('disabled', 'disabled');
+                },
+                complete: function() {
+                    elem.attr('disabled', null);
+                }
+            })
+                .done(function(response) {
+                    if (response.success) {
+                        callback.call(this, elem, response);
+                    } else {
+                        var msg = response.error_message;
+                        if (msg) {
+                            window.alert($.mage.__(msg));
+                        }
+                    }
+                })
+                .fail(function(error) {
+                    console.log(JSON.stringify(error));
+                });
+        },
+
+        _refreshItemQty: function(elem, qty) {
+            if (qty != undefined) {
+                var itemId = elem.data('cart-item');
+                $('#cart-item-' + itemId + '-qty').data('item-qty', qty);
+            }
+        },
+
+        _refreshQty: function(qty, text) {
+            if (qty != undefined && text != undefined) {
+                var self = this;
+                $(this.options.minicart.qty).fadeOut('slow', function() {
+                    $(self.options.minicart.qty).html('<span class="count">' + qty + '</span>' + text);
+                }).fadeIn();
+            }
+        },
+
+        _refreshSubtotal: function(val) {
+            if (val != undefined) {
+                var self = this;
+                $(this.options.minicart.subtotal).fadeOut('slow', function() {
+                    $(self.options.minicart.subtotal).replaceWith(val);
+                }).fadeIn();
+            }
+        },
+
+        _refreshShowcart: function(qty, text) {
+            if (qty != undefined && text != undefined) {
+                var self = this;
+                $(this.options.showcart.qty).fadeOut('slow', function() {
+                    $(self.options.showcart.qty).text(qty);
+                }).fadeIn();
+                $(this.options.showcart.label).fadeOut('slow', function() {
+                    $(self.options.showcart.label).text(text);
+                }).fadeIn();
+            }
+        },
+
+        /**
+         * Calculate height of minicart list
+         *
+         * @private
+         */
+        _calcHeight: function() {
+            var self = this,
+                height = 0,
+                counter = this.options.maxItemsVisible,
+                target = $(this.options.minicart.list)
+                    .clone()
+                    .attr('style', 'position: absolute !important; top: -10000 !important;')
+                    .appendTo('body');
+
+            this.scrollHeight = 0;
+            target.children().each(function() {
+                if (counter-- > 0) {
+                    height += $(this).height() - 15;
+                }
+                self.scrollHeight += $(this).height() - 15;
+            });
+
+            target.remove();
+
+            $(this.options.minicart.list).css('height', height);
         }
     });
 
     return $.mage.sidebar;
-});
\ No newline at end of file
+});
diff --git a/app/code/Magento/Cms/Api/BlockRepositoryInterface.php b/app/code/Magento/Cms/Api/BlockRepositoryInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..e9834b821a66be6531ecfcce99fe1800a38f62f7
--- /dev/null
+++ b/app/code/Magento/Cms/Api/BlockRepositoryInterface.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Cms\Api;
+
+use Magento\Framework\Api\SearchCriteriaInterface;
+
+/**
+ * CMS block CRUD interface.
+ */
+interface BlockRepositoryInterface
+{
+    /**
+     * Save block.
+     *
+     * @param Data\BlockInterface $block
+     * @return Data\BlockInterface
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    public function save(Data\BlockInterface $block);
+
+    /**
+     * Retrieve block.
+     *
+     * @param int $blockId
+     * @return Data\BlockInterface
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    public function getById($blockId);
+
+    /**
+     * Retrieve blocks matching the specified criteria.
+     *
+     * @param SearchCriteriaInterface $searchCriteria
+     * @return \Magento\Framework\Api\SearchResultsInterface
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    public function getList(SearchCriteriaInterface $searchCriteria);
+
+    /**
+     * Delete block.
+     *
+     * @param Data\BlockInterface $block
+     * @return bool true on success
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    public function delete(Data\BlockInterface $block);
+
+    /**
+     * Delete block by ID.
+     *
+     * @param int $blockId
+     * @return bool true on success
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    public function deleteById($blockId);
+}
diff --git a/app/code/Magento/Cms/Api/Data/BlockInterface.php b/app/code/Magento/Cms/Api/Data/BlockInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..d26f46cda2fb2cfe337413133be03785dfbbbbfa
--- /dev/null
+++ b/app/code/Magento/Cms/Api/Data/BlockInterface.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Cms\Api\Data;
+
+/**
+ * CMS block interface.
+ */
+interface BlockInterface
+{
+    /**#@+
+     * Constants for keys of data array. Identical to the name of the getter in snake case
+     */
+    const BLOCK_ID      = 'block_id';
+    const IDENTIFIER    = 'identifier';
+    const TITLE         = 'title';
+    const CONTENT       = 'content';
+    const CREATION_TIME = 'creation_time';
+    const UPDATE_TIME   = 'update_time';
+    const IS_ACTIVE     = 'is_active';
+    /**#@-*/
+
+    /**
+     * Get ID
+     *
+     * @return int
+     */
+    public function getId();
+
+    /**
+     * Get identifier
+     *
+     * @return string
+     */
+    public function getIdentifier();
+
+    /**
+     * Get title
+     *
+     * @return string
+     */
+    public function getTitle();
+
+    /**
+     * Get content
+     *
+     * @return string
+     */
+    public function getContent();
+
+    /**
+     * Get creation time
+     *
+     * @return string
+     */
+    public function getCreationTime();
+
+    /**
+     * Get update time
+     *
+     * @return string
+     */
+    public function getUpdateTime();
+
+    /**
+     * Is active
+     *
+     * @return bool
+     */
+    public function isActive();
+
+    /**
+     * Set ID
+     *
+     * @param int $id
+     * @return BlockInterface
+     */
+    public function setId($id);
+
+    /**
+     * Set identifier
+     *
+     * @param string $identifier
+     * @return BlockInterface
+     */
+    public function setIdentifier($identifier);
+
+    /**
+     * Set title
+     *
+     * @param string $title
+     * @return BlockInterface
+     */
+    public function setTitle($title);
+
+    /**
+     * Set content
+     *
+     * @param string $content
+     * @return BlockInterface
+     */
+    public function setContent($content);
+
+    /**
+     * Set creation time
+     *
+     * @param string $creationTime
+     * @return BlockInterface
+     */
+    public function setCreationTime($creationTime);
+
+    /**
+     * Set update time
+     *
+     * @param string $updateTime
+     * @return BlockInterface
+     */
+    public function setUpdateTime($updateTime);
+
+    /**
+     * Set is active
+     *
+     * @param bool|int $isActive
+     * @return BlockInterface
+     */
+    public function setIsActive($isActive);
+}
diff --git a/app/code/Magento/Cms/Api/Data/BlockSearchResultsInterface.php b/app/code/Magento/Cms/Api/Data/BlockSearchResultsInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..715790c17343691226d8020f45ae896aee4eb5df
--- /dev/null
+++ b/app/code/Magento/Cms/Api/Data/BlockSearchResultsInterface.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Cms\Api\Data;
+
+use Magento\Framework\Api\SearchResultsInterface;
+
+/**
+ * Interface for cms block search results.
+ */
+interface BlockSearchResultsInterface extends SearchResultsInterface
+{
+    /**
+     * Get blocks list.
+     *
+     * @return \Magento\Cms\Api\Data\BlockInterface[]
+     */
+    public function getItems();
+
+    /**
+     * Set blocks list.
+     *
+     * @param \Magento\Cms\Api\Data\BlockInterface[] $items
+     * @return $this
+     */
+    public function setItems(array $items = null);
+}
diff --git a/app/code/Magento/Cms/Api/Data/PageInterface.php b/app/code/Magento/Cms/Api/Data/PageInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..8e03d0ed1ffde5e14a18ae2effb77062b508ffcf
--- /dev/null
+++ b/app/code/Magento/Cms/Api/Data/PageInterface.php
@@ -0,0 +1,305 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Cms\Api\Data;
+
+/**
+ * CMS page interface.
+ */
+interface PageInterface
+{
+    /**#@+
+     * Constants for keys of data array. Identical to the name of the getter in snake case
+     */
+    const PAGE_ID                  = 'page_id';
+    const IDENTIFIER               = 'identifier';
+    const TITLE                    = 'title';
+    const PAGE_LAYOUT              = 'page_layout';
+    const META_KEYWORDS            = 'meta_keywords';
+    const META_DESCRIPTION         = 'meta_description';
+    const CONTENT_HEADING          = 'content_heading';
+    const CONTENT                  = 'content';
+    const CREATION_TIME            = 'creation_time';
+    const UPDATE_TIME              = 'update_time';
+    const SORT_ORDER               = 'sort_order';
+    const LAYOUT_UPDATE_XML        = 'layout_update_xml';
+    const CUSTOM_THEME             = 'custom_theme';
+    const CUSTOM_ROOT_TEMPLATE     = 'custom_root_template';
+    const CUSTOM_LAYOUT_UPDATE_XML = 'custom_layout_update_xml';
+    const CUSTOM_THEME_FROM        = 'custom_theme_from';
+    const CUSTOM_THEME_TO          = 'custom_theme_to';
+    const IS_ACTIVE                = 'is_active';
+    /**#@-*/
+
+    /**
+     * Get ID
+     *
+     * @return int
+     */
+    public function getId();
+
+    /**
+     * Get identifier
+     *
+     * @return string
+     */
+    public function getIdentifier();
+
+    /**
+     * Get title
+     *
+     * @return string
+     */
+    public function getTitle();
+
+    /**
+     * Get page layout
+     *
+     * @return string
+     */
+    public function getPageLayout();
+
+    /**
+     * Get meta keywords
+     *
+     * @return string
+     */
+    public function getMetaKeywords();
+
+    /**
+     * Get meta description
+     *
+     * @return string
+     */
+    public function getMetaDescription();
+
+    /**
+     * Get content heading
+     *
+     * @return string
+     */
+    public function getContentHeading();
+
+    /**
+     * Get content
+     *
+     * @return string
+     */
+    public function getContent();
+
+    /**
+     * Get creation time
+     *
+     * @return string
+     */
+    public function getCreationTime();
+
+    /**
+     * Get update time
+     *
+     * @return string
+     */
+    public function getUpdateTime();
+
+    /**
+     * Get sort order
+     *
+     * @return string
+     */
+    public function getSortOrder();
+
+    /**
+     * Get layout update xml
+     *
+     * @return string
+     */
+    public function getLayoutUpdateXml();
+
+    /**
+     * Get custom theme
+     *
+     * @return string
+     */
+    public function getCustomTheme();
+
+    /**
+     * Get custom root template
+     *
+     * @return string
+     */
+    public function getCustomRootTemplate();
+
+    /**
+     * Get custom layout update xml
+     *
+     * @return string
+     */
+    public function getCustomLayoutUpdateXml();
+
+    /**
+     * Get custom theme from
+     *
+     * @return string
+     */
+    public function getCustomThemeFrom();
+
+    /**
+     * Get custom theme to
+     *
+     * @return string
+     */
+    public function getCustomThemeTo();
+
+    /**
+     * Is active
+     *
+     * @return bool
+     */
+    public function isActive();
+
+    /**
+     * Set ID
+     *
+     * @param int $id
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setId($id);
+
+    /**
+     * Set identifier
+     *
+     * @param string $identifier
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setIdentifier($identifier);
+
+    /**
+     * Set title
+     *
+     * @param string $title
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setTitle($title);
+
+    /**
+     * Set page layout
+     *
+     * @param string $pageLayout
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setPageLayout($pageLayout);
+
+    /**
+     * Set meta keywords
+     *
+     * @param string $metaKeywords
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setMetaKeywords($metaKeywords);
+
+    /**
+     * Set meta description
+     *
+     * @param string $metaDescription
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setMetaDescription($metaDescription);
+
+    /**
+     * Set content heading
+     *
+     * @param string $contentHeading
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setContentHeading($contentHeading);
+
+    /**
+     * Set content
+     *
+     * @param string $content
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setContent($content);
+
+    /**
+     * Set creation time
+     *
+     * @param string $creationTime
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setCreationTime($creationTime);
+
+    /**
+     * Set update time
+     *
+     * @param string $updateTime
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setUpdateTime($updateTime);
+
+    /**
+     * Set sort order
+     *
+     * @param string $sortOrder
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setSortOrder($sortOrder);
+
+    /**
+     * Set layout update xml
+     *
+     * @param string $layoutUpdateXml
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setLayoutUpdateXml($layoutUpdateXml);
+
+    /**
+     * Set custom theme
+     *
+     * @param string $customTheme
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setCustomTheme($customTheme);
+
+    /**
+     * Set custom root template
+     *
+     * @param string $customRootTemplate
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setCustomRootTemplate($customRootTemplate);
+
+    /**
+     * Set custom layout update xml
+     *
+     * @param string $customLayoutUpdateXml
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setCustomLayoutUpdateXml($customLayoutUpdateXml);
+
+    /**
+     * Set custom theme from
+     *
+     * @param string $customThemeFrom
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setCustomThemeFrom($customThemeFrom);
+
+    /**
+     * Set custom theme to
+     *
+     * @param string $customThemeTo
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setCustomThemeTo($customThemeTo);
+
+    /**
+     * Set is active
+     *
+     * @param int|bool $isActive
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setIsActive($isActive);
+}
diff --git a/app/code/Magento/Cms/Api/Data/PageSearchResultsInterface.php b/app/code/Magento/Cms/Api/Data/PageSearchResultsInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..160d93d172c214ecba5dd13e4e482cc4754772c6
--- /dev/null
+++ b/app/code/Magento/Cms/Api/Data/PageSearchResultsInterface.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Cms\Api\Data;
+
+use Magento\Framework\Api\SearchResultsInterface;
+
+/**
+ * Interface for cms page search results.
+ */
+interface PageSearchResultsInterface extends SearchResultsInterface
+{
+    /**
+     * Get pages list.
+     *
+     * @return \Magento\Cms\Api\Data\PageInterface[]
+     */
+    public function getItems();
+
+    /**
+     * Set pages list.
+     *
+     * @param \Magento\Cms\Api\Data\PageInterface[] $items
+     * @return $this
+     */
+    public function setItems(array $items = null);
+}
diff --git a/app/code/Magento/Cms/Api/PageRepositoryInterface.php b/app/code/Magento/Cms/Api/PageRepositoryInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..9dcf95d572fd533036999b4863bd1240ed7ad30e
--- /dev/null
+++ b/app/code/Magento/Cms/Api/PageRepositoryInterface.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Cms\Api;
+
+use Magento\Framework\Api\SearchCriteriaInterface;
+
+/**
+ * CMS page CRUD interface.
+ */
+interface PageRepositoryInterface
+{
+    /**
+     * Save page.
+     *
+     * @param Data\PageInterface $page
+     * @return Data\PageInterface
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    public function save(Data\PageInterface $page);
+
+    /**
+     * Retrieve page.
+     *
+     * @param int $pageId
+     * @return Data\PageInterface
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    public function getById($pageId);
+
+    /**
+     * Retrieve pages matching the specified criteria.
+     *
+     * @param SearchCriteriaInterface $searchCriteria
+     * @return \Magento\Framework\Api\SearchResultsInterface
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    public function getList(SearchCriteriaInterface $searchCriteria);
+
+    /**
+     * Delete page.
+     *
+     * @param Data\PageInterface $page
+     * @return bool true on success
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    public function delete(Data\PageInterface $page);
+
+    /**
+     * Delete page by ID.
+     *
+     * @param int $pageId
+     * @return bool true on success
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    public function deleteById($pageId);
+}
diff --git a/app/code/Magento/Cms/Block/Adminhtml/Block/Widget/Chooser.php b/app/code/Magento/Cms/Block/Adminhtml/Block/Widget/Chooser.php
index 93f8f338149a480ebb4502291daaa7a538263099..fed2f67da6f177806559e463deb8fda56a2fbb3f 100644
--- a/app/code/Magento/Cms/Block/Adminhtml/Block/Widget/Chooser.php
+++ b/app/code/Magento/Cms/Block/Adminhtml/Block/Widget/Chooser.php
@@ -16,7 +16,7 @@ class Chooser extends \Magento\Backend\Block\Widget\Grid\Extended
     protected $_blockFactory;
 
     /**
-     * @var \Magento\Cms\Model\Resource\Block\Grid\CollectionFactory
+     * @var \Magento\Cms\Model\Resource\Block\CollectionFactory
      */
     protected $_collectionFactory;
 
@@ -24,14 +24,14 @@ class Chooser extends \Magento\Backend\Block\Widget\Grid\Extended
      * @param \Magento\Backend\Block\Template\Context $context
      * @param \Magento\Backend\Helper\Data $backendHelper
      * @param \Magento\Cms\Model\BlockFactory $blockFactory
-     * @param \Magento\Cms\Model\Resource\Block\Grid\CollectionFactory $collectionFactory
+     * @param \Magento\Cms\Model\Resource\Block\CollectionFactory $collectionFactory
      * @param array $data
      */
     public function __construct(
         \Magento\Backend\Block\Template\Context $context,
         \Magento\Backend\Helper\Data $backendHelper,
         \Magento\Cms\Model\BlockFactory $blockFactory,
-        \Magento\Cms\Model\Resource\Block\Grid\CollectionFactory $collectionFactory,
+        \Magento\Cms\Model\Resource\Block\CollectionFactory $collectionFactory,
         array $data = []
     ) {
         $this->_blockFactory = $blockFactory;
diff --git a/app/code/Magento/Cms/Block/Adminhtml/Page/Grid.php b/app/code/Magento/Cms/Block/Adminhtml/Page/Grid.php
index 0580ceeaeb0d16706547ec6831b197c142e1cd27..af9f8d533c2d87e95e8fbcbd8a205f2dcec7e873 100644
--- a/app/code/Magento/Cms/Block/Adminhtml/Page/Grid.php
+++ b/app/code/Magento/Cms/Block/Adminhtml/Page/Grid.php
@@ -11,7 +11,7 @@ namespace Magento\Cms\Block\Adminhtml\Page;
 class Grid extends \Magento\Backend\Block\Widget\Grid\Extended
 {
     /**
-     * @var \Magento\Cms\Model\Resource\Page\Grid\CollectionFactory
+     * @var \Magento\Cms\Model\Resource\Page\CollectionFactory
      */
     protected $_collectionFactory;
 
@@ -29,7 +29,7 @@ class Grid extends \Magento\Backend\Block\Widget\Grid\Extended
      * @param \Magento\Backend\Block\Template\Context $context
      * @param \Magento\Backend\Helper\Data $backendHelper
      * @param \Magento\Cms\Model\Page $cmsPage
-     * @param \Magento\Cms\Model\Resource\Page\Grid\CollectionFactory $collectionFactory
+     * @param \Magento\Cms\Model\Resource\Page\CollectionFactory $collectionFactory
      * @param \Magento\Framework\View\Model\PageLayout\Config\BuilderInterface $pageLayoutBuilder
      * @param array $data
      */
@@ -37,7 +37,7 @@ class Grid extends \Magento\Backend\Block\Widget\Grid\Extended
         \Magento\Backend\Block\Template\Context $context,
         \Magento\Backend\Helper\Data $backendHelper,
         \Magento\Cms\Model\Page $cmsPage,
-        \Magento\Cms\Model\Resource\Page\Grid\CollectionFactory $collectionFactory,
+        \Magento\Cms\Model\Resource\Page\CollectionFactory $collectionFactory,
         \Magento\Framework\View\Model\PageLayout\Config\BuilderInterface $pageLayoutBuilder,
         array $data = []
     ) {
@@ -66,7 +66,7 @@ class Grid extends \Magento\Backend\Block\Widget\Grid\Extended
     protected function _prepareCollection()
     {
         $collection = $this->_collectionFactory->create();
-        /* @var $collection \Magento\Cms\Model\Resource\Page\Grid\Collection */
+        /* @var $collection \Magento\Cms\Model\Resource\Page\Collection */
         $collection->setFirstStoreFlag(true);
         $this->setCollection($collection);
 
diff --git a/app/code/Magento/Cms/Block/Adminhtml/Page/Widget/Chooser.php b/app/code/Magento/Cms/Block/Adminhtml/Page/Widget/Chooser.php
index f6efab805aa28ef9fd36d9bf5eca387adf8914df..addaf3f4926b8e05f48833b16e540eb73ad295ef 100644
--- a/app/code/Magento/Cms/Block/Adminhtml/Page/Widget/Chooser.php
+++ b/app/code/Magento/Cms/Block/Adminhtml/Page/Widget/Chooser.php
@@ -23,7 +23,7 @@ class Chooser extends \Magento\Backend\Block\Widget\Grid\Extended
     protected $_pageFactory;
 
     /**
-     * @var \Magento\Cms\Model\Resource\Page\Grid\CollectionFactory
+     * @var \Magento\Cms\Model\Resource\Page\CollectionFactory
      */
     protected $_collectionFactory;
 
@@ -37,7 +37,7 @@ class Chooser extends \Magento\Backend\Block\Widget\Grid\Extended
      * @param \Magento\Backend\Helper\Data $backendHelper
      * @param \Magento\Cms\Model\Page $cmsPage
      * @param \Magento\Cms\Model\PageFactory $pageFactory
-     * @param \Magento\Cms\Model\Resource\Page\Grid\CollectionFactory $collectionFactory
+     * @param \Magento\Cms\Model\Resource\Page\CollectionFactory $collectionFactory
      * @param \Magento\Framework\View\Model\PageLayout\Config\BuilderInterface $pageLayoutBuilder
      * @param array $data
      */
@@ -46,7 +46,7 @@ class Chooser extends \Magento\Backend\Block\Widget\Grid\Extended
         \Magento\Backend\Helper\Data $backendHelper,
         \Magento\Cms\Model\Page $cmsPage,
         \Magento\Cms\Model\PageFactory $pageFactory,
-        \Magento\Cms\Model\Resource\Page\Grid\CollectionFactory $collectionFactory,
+        \Magento\Cms\Model\Resource\Page\CollectionFactory $collectionFactory,
         \Magento\Framework\View\Model\PageLayout\Config\BuilderInterface $pageLayoutBuilder,
         array $data = []
     ) {
@@ -141,7 +141,7 @@ class Chooser extends \Magento\Backend\Block\Widget\Grid\Extended
     protected function _prepareCollection()
     {
         $collection = $this->_collectionFactory->create();
-        /* @var $collection \Magento\Cms\Model\Resource\Page\Grid\CollectionFactory */
+        /* @var $collection \Magento\Cms\Model\Resource\Page\CollectionFactory */
         $collection->setFirstStoreFlag(true);
         $this->setCollection($collection);
 
diff --git a/app/code/Magento/Cms/Block/Block.php b/app/code/Magento/Cms/Block/Block.php
index 2f8f28e4334fc17c2f112217efbb9aad8c4f3cf0..707dbbe40d754d3708cd3c13a284e13fe5720a58 100644
--- a/app/code/Magento/Cms/Block/Block.php
+++ b/app/code/Magento/Cms/Block/Block.php
@@ -68,7 +68,7 @@ class Block extends \Magento\Framework\View\Element\AbstractBlock implements \Ma
             /** @var \Magento\Cms\Model\Block $block */
             $block = $this->_blockFactory->create();
             $block->setStoreId($storeId)->load($blockId);
-            if ($block->getIsActive()) {
+            if ($block->isActive()) {
                 $html = $this->_filterProvider->getBlockFilter()->setStoreId($storeId)->filter($block->getContent());
             }
         }
diff --git a/app/code/Magento/Cms/Block/Widget/Block.php b/app/code/Magento/Cms/Block/Widget/Block.php
index 66f31639c36f1bb13a97f460f89a324f28895eac..7c83169d945f128d2d10380664f80a7f82123a7a 100644
--- a/app/code/Magento/Cms/Block/Widget/Block.php
+++ b/app/code/Magento/Cms/Block/Widget/Block.php
@@ -70,7 +70,7 @@ class Block extends \Magento\Framework\View\Element\Template implements \Magento
             /** @var \Magento\Cms\Model\Block $block */
             $block = $this->_blockFactory->create();
             $block->setStoreId($storeId)->load($blockId);
-            if ($block->getIsActive()) {
+            if ($block->isActive()) {
                 $this->setText(
                     $this->_filterProvider->getBlockFilter()->setStoreId($storeId)->filter($block->getContent())
                 );
diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Page/MassDelete.php b/app/code/Magento/Cms/Controller/Adminhtml/Page/MassDelete.php
index 95ec6e5169e34519a92e893e5f3bc26e76a99e95..a87024f3ea1e622f46e7f1d540e5f9081932bcaf 100644
--- a/app/code/Magento/Cms/Controller/Adminhtml/Page/MassDelete.php
+++ b/app/code/Magento/Cms/Controller/Adminhtml/Page/MassDelete.php
@@ -23,7 +23,7 @@ class MassDelete extends AbstractMassDelete
      *
      * @var string
      */
-    protected $collection = 'Magento\Cms\Model\Resource\Page\Grid\Collection';
+    protected $collection = 'Magento\Cms\Model\Resource\Page\Collection';
 
     /**
      * Page model
diff --git a/app/code/Magento/Cms/Model/Block.php b/app/code/Magento/Cms/Model/Block.php
index 14227352f81bb7575785bfb46af36585111ed1ab..8fd712570825f235b4959b353906974eefb69a46 100644
--- a/app/code/Magento/Cms/Model/Block.php
+++ b/app/code/Magento/Cms/Model/Block.php
@@ -5,6 +5,7 @@
  */
 namespace Magento\Cms\Model;
 
+use Magento\Cms\Api\Data\BlockInterface;
 use Magento\Framework\Object\IdentityInterface;
 
 /**
@@ -12,28 +13,14 @@ use Magento\Framework\Object\IdentityInterface;
  *
  * @method \Magento\Cms\Model\Resource\Block _getResource()
  * @method \Magento\Cms\Model\Resource\Block getResource()
- * @method \Magento\Cms\Model\Block setTitle(string $value)
- * @method \Magento\Cms\Model\Block setIdentifier(string $value)
- * @method \Magento\Cms\Model\Block setContent(string $value)
- * @method \Magento\Cms\Model\Block setCreationTime(string $value)
- * @method \Magento\Cms\Model\Block setUpdateTime(string $value)
- * @method \Magento\Cms\Model\Block setIsActive(int $value)
  */
-class Block extends \Magento\Framework\Model\AbstractModel implements IdentityInterface
+class Block extends \Magento\Framework\Model\AbstractModel implements BlockInterface, IdentityInterface
 {
     /**
      * CMS block cache tag
      */
     const CACHE_TAG = 'cms_block';
 
-    const ID = 'block_id';
-    const IDENTIFIER = 'identifier';
-    const TITLE = 'title';
-    const CONTENT = 'content';
-    const CREATION_TIME = 'creation_time';
-    const UPDATE_TIME ='update_time';
-    const IS_ACTIVE ='is_active';
-
     /**
      * @var string
      */
@@ -88,7 +75,7 @@ class Block extends \Magento\Framework\Model\AbstractModel implements IdentityIn
      */
     public function getId()
     {
-        return $this->_getData(self::ID);
+        return $this->getData(self::BLOCK_ID);
     }
 
     /**
@@ -98,7 +85,7 @@ class Block extends \Magento\Framework\Model\AbstractModel implements IdentityIn
      */
     public function getIdentifier()
     {
-        return (string) $this->_getData(self::IDENTIFIER);
+        return (string)$this->getData(self::IDENTIFIER);
     }
 
     /**
@@ -108,7 +95,7 @@ class Block extends \Magento\Framework\Model\AbstractModel implements IdentityIn
      */
     public function getTitle()
     {
-        return $this->_getData(self::TITLE);
+        return $this->getData(self::TITLE);
     }
 
     /**
@@ -118,7 +105,7 @@ class Block extends \Magento\Framework\Model\AbstractModel implements IdentityIn
      */
     public function getContent()
     {
-        return $this->_getData(self::CONTENT);
+        return $this->getData(self::CONTENT);
     }
 
     /**
@@ -128,7 +115,7 @@ class Block extends \Magento\Framework\Model\AbstractModel implements IdentityIn
      */
     public function getCreationTime()
     {
-        return $this->_getData(self::CREATION_TIME);
+        return $this->getData(self::CREATION_TIME);
     }
 
     /**
@@ -138,16 +125,93 @@ class Block extends \Magento\Framework\Model\AbstractModel implements IdentityIn
      */
     public function getUpdateTime()
     {
-        return $this->_getData(self::UPDATE_TIME);
+        return $this->getData(self::UPDATE_TIME);
     }
 
     /**
-     * Retrieve block status
+     * Is active
      *
-     * @return int
+     * @return bool
+     */
+    public function isActive()
+    {
+        return (bool)$this->getData(self::IS_ACTIVE);
+    }
+
+    /**
+     * Set ID
+     *
+     * @param int $id
+     * @return BlockInterface
+     */
+    public function setId($id)
+    {
+        return $this->setData(self::BLOCK_ID, $id);
+    }
+
+    /**
+     * Set identifier
+     *
+     * @param string $identifier
+     * @return BlockInterface
+     */
+    public function setIdentifier($identifier)
+    {
+        return $this->setData(self::IDENTIFIER, $identifier);
+    }
+
+    /**
+     * Set title
+     *
+     * @param string $title
+     * @return BlockInterface
+     */
+    public function setTitle($title)
+    {
+        return $this->setData(self::TITLE, $title);
+    }
+
+    /**
+     * Set content
+     *
+     * @param string $content
+     * @return BlockInterface
+     */
+    public function setContent($content)
+    {
+        return $this->setData(self::CONTENT, $content);
+    }
+
+    /**
+     * Set creation time
+     *
+     * @param string $creationTime
+     * @return BlockInterface
+     */
+    public function setCreationTime($creationTime)
+    {
+        return $this->setData(self::CREATION_TIME, $creationTime);
+    }
+
+    /**
+     * Set update time
+     *
+     * @param string $updateTime
+     * @return BlockInterface
+     */
+    public function setUpdateTime($updateTime)
+    {
+        return $this->setData(self::UPDATE_TIME, $updateTime);
+    }
+
+    /**
+     * Set is active
+     *
+     * @param bool|int $isActive
+     * @return BlockInterface
      */
-    public function getIsActive()
+    public function setIsActive($isActive)
     {
-        return $this->_getData(self::IS_ACTIVE);
+        return $this->setData(self::IS_ACTIVE, $isActive);
     }
 }
diff --git a/app/code/Magento/Cms/Model/BlockCriteriaInterface.php b/app/code/Magento/Cms/Model/BlockCriteriaInterface.php
deleted file mode 100644
index 358551b163cdcfa6be96d49b4c2c007c31525f1a..0000000000000000000000000000000000000000
--- a/app/code/Magento/Cms/Model/BlockCriteriaInterface.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Cms\Model;
-
-/**
- * Interface BlockCriteriaInterface
- */
-interface BlockCriteriaInterface extends \Magento\Framework\Api\CriteriaInterface
-{
-    /**
-     * Set first store flag
-     *
-     * @param bool $flag
-     * @return void
-     */
-    public function setFirstStoreFlag($flag = false);
-
-    /**
-     * Add filter by store
-     *
-     * @param int $storeId
-     * @param bool $withAdmin
-     * @return void
-     */
-    public function addStoreFilter($storeId, $withAdmin = true);
-}
diff --git a/app/code/Magento/Cms/Model/BlockRepository.php b/app/code/Magento/Cms/Model/BlockRepository.php
index 520add71eb28b864280d9cc2979859400fb04c6f..be1498fc8667553ba1f4ad4f8ccd93ac61d57b97 100644
--- a/app/code/Magento/Cms/Model/BlockRepository.php
+++ b/app/code/Magento/Cms/Model/BlockRepository.php
@@ -5,70 +5,82 @@
  */
 namespace Magento\Cms\Model;
 
+use Magento\Cms\Api\Data;
+use Magento\Cms\Api\BlockRepositoryInterface;
+use Magento\Framework\Api\DataObjectHelper;
+use Magento\Framework\Api\SearchCriteriaInterface;
 use Magento\Framework\Exception\CouldNotDeleteException;
 use Magento\Framework\Exception\CouldNotSaveException;
 use Magento\Framework\Exception\NoSuchEntityException;
 
 /**
  * Class BlockRepository
- * @api
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
-class BlockRepository
+class BlockRepository implements BlockRepositoryInterface
 {
     /**
-     * @var \Magento\Cms\Model\Resource\Block
+     * @var Resource\Block
      */
     protected $resource;
 
     /**
-     * @var \Magento\Cms\Model\BlockFactory
+     * @var BlockFactory
      */
     protected $blockFactory;
 
     /**
-     * @var \Magento\Cms\Model\Resource\Block\CollectionFactory
+     * @var Resource\Block\CollectionFactory
      */
     protected $blockCollectionFactory;
 
     /**
-     * @var \Magento\Framework\DB\QueryBuilderFactory
+     * @var Data\BlockSearchResultsInterfaceFactory
      */
-    protected $queryBuilderFactory;
+    protected $searchResultsFactory;
 
     /**
-     * @var \Magento\Framework\DB\MapperFactory
+     * @var DataObjectHelper
      */
-    protected $mapperFactory;
+    protected $dataObjectHelper;
 
     /**
-     * @param \Magento\Cms\Model\Resource\Block $resource
-     * @param \Magento\Cms\Model\BlockFactory $blockFactory
-     * @param \Magento\Cms\Model\Resource\Block\CollectionFactory $blockCollectionFactory
-     * @param \Magento\Framework\DB\QueryBuilderFactory $queryBuilderFactory
-     * @param \Magento\Framework\DB\MapperFactory $mapperFactory
+     * @var Data\BlockInterfaceFactory
+     */
+    protected $dataBlockFactory;
+
+    /**
+     * @param Resource\Block $resource
+     * @param BlockFactory $blockFactory
+     * @param Data\BlockInterfaceFactory $dataBlockFactory
+     * @param Resource\Block\CollectionFactory $blockCollectionFactory
+     * @param Data\BlockSearchResultsInterfaceFactory $searchResultsFactory
+     * @param DataObjectHelper $dataObjectHelper
      */
     public function __construct(
-        \Magento\Cms\Model\Resource\Block $resource,
-        \Magento\Cms\Model\BlockFactory $blockFactory,
-        \Magento\Cms\Model\Resource\Block\CollectionFactory $blockCollectionFactory,
-        \Magento\Framework\DB\QueryBuilderFactory $queryBuilderFactory,
-        \Magento\Framework\DB\MapperFactory $mapperFactory
+        Resource\Block $resource,
+        BlockFactory $blockFactory,
+        Data\BlockInterfaceFactory $dataBlockFactory,
+        Resource\Block\CollectionFactory $blockCollectionFactory,
+        Data\BlockSearchResultsInterfaceFactory $searchResultsFactory,
+        DataObjectHelper $dataObjectHelper
     ) {
         $this->resource = $resource;
         $this->blockFactory = $blockFactory;
         $this->blockCollectionFactory = $blockCollectionFactory;
-        $this->queryBuilderFactory = $queryBuilderFactory;
-        $this->mapperFactory = $mapperFactory;
+        $this->searchResultsFactory = $searchResultsFactory;
+        $this->dataObjectHelper = $dataObjectHelper;
+        $this->dataBlockFactory = $dataBlockFactory;
     }
 
     /**
      * Save Block data
      *
-     * @param \Magento\Cms\Model\Block $block
-     * @return \Magento\Cms\Model\Block
+     * @param Data\BlockInterface $block
+     * @return Block
      * @throws CouldNotSaveException
      */
-    public function save(\Magento\Cms\Model\Block $block)
+    public function save(Data\BlockInterface $block)
     {
         try {
             $this->resource->save($block);
@@ -82,10 +94,10 @@ class BlockRepository
      * Load Block data by given Block Identity
      *
      * @param string $blockId
-     * @return \Magento\Cms\Model\Block
+     * @return Block
      * @throws \Magento\Framework\Exception\NoSuchEntityException
      */
-    public function get($blockId)
+    public function getById($blockId)
     {
         $block = $this->blockFactory->create();
         $this->resource->load($block, $blockId);
@@ -98,27 +110,65 @@ class BlockRepository
     /**
      * Load Block data collection by given search criteria
      *
-     * @param \Magento\Cms\Model\BlockCriteriaInterface $criteria
-     * @return \Magento\Cms\Model\Resource\Block\Collection
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     * @param SearchCriteriaInterface $criteria
+     * @return Resource\Block\Collection
      */
-    public function getList(\Magento\Cms\Model\BlockCriteriaInterface $criteria)
+    public function getList(SearchCriteriaInterface $criteria)
     {
-        $queryBuilder = $this->queryBuilderFactory->create();
-        $queryBuilder->setCriteria($criteria);
-        $queryBuilder->setResource($this->resource);
-        $query = $queryBuilder->create();
-        $collection = $this->blockCollectionFactory->create(['query' => $query]);
-        return $collection;
+        $searchResults = $this->searchResultsFactory->create();
+        $searchResults->setSearchCriteria($criteria);
+
+        $collection = $this->blockCollectionFactory->create();
+        foreach ($criteria->getFilterGroups() as $filterGroup) {
+            $fields = [];
+            $conditions = [];
+            foreach ($filterGroup->getFilters() as $filter) {
+                if ($filter->getField() === 'store_id') {
+                    $collection->addStoreFilter($filter->getValue(), false);
+                    continue;
+                }
+                $condition = $filter->getConditionType() ?: 'eq';
+                $fields[] = ['attribute' => $filter->getField(), $condition => $filter->getValue()];
+            }
+            if ($fields) {
+                $collection->addFieldToFilter($fields, $conditions);
+            }
+        }
+        $searchResults->setTotalCount($collection->getSize());
+        $sortOrders = $criteria->getSortOrders();
+        if ($sortOrders) {
+            foreach ($sortOrders as $sortOrder) {
+                $collection->addOrder(
+                    $sortOrder->getField(),
+                    ($sortOrder->getDirection() == SearchCriteriaInterface::SORT_ASC) ? 'ASC' : 'DESC'
+                );
+            }
+        }
+        $collection->setCurPage($criteria->getCurrentPage());
+        $collection->setPageSize($criteria->getPageSize());
+        $blocks = [];
+        /** @var Block $blockModel */
+        foreach ($collection as $blockModel) {
+            $blocks[] = $this->dataObjectHelper->populateWithArray(
+                $this->dataBlockFactory->create(),
+                $blockModel->getData(),
+                'Magento\Cms\Api\Data\BlockInterface'
+            );
+        }
+        $searchResults->setItems($blocks);
+        return $searchResults;
     }
 
     /**
      * Delete Block
      *
-     * @param \Magento\Cms\Model\Block $block
+     * @param Data\BlockInterface $block
      * @return bool
-     * @throws \Magento\Framework\Exception\CouldNotDeleteException
+     * @throws CouldNotDeleteException
      */
-    public function delete(\Magento\Cms\Model\Block $block)
+    public function delete(Data\BlockInterface $block)
     {
         try {
             $this->resource->delete($block);
@@ -133,11 +183,11 @@ class BlockRepository
      *
      * @param string $blockId
      * @return bool
-     * @throws \Magento\Framework\Exception\CouldNotDeleteException
-     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     * @throws CouldNotDeleteException
+     * @throws NoSuchEntityException
      */
     public function deleteById($blockId)
     {
-        return $this->delete($this->get($blockId));
+        return $this->delete($this->getById($blockId));
     }
 }
diff --git a/app/code/Magento/Cms/Model/Config/Source/Page.php b/app/code/Magento/Cms/Model/Config/Source/Page.php
index 4ed69001f1f9e0d0a747bcb7962f0a33b9c87a4a..6d0d87680ef5a386c7fde21be6a542beb1335793 100644
--- a/app/code/Magento/Cms/Model/Config/Source/Page.php
+++ b/app/code/Magento/Cms/Model/Config/Source/Page.php
@@ -5,6 +5,8 @@
  */
 namespace Magento\Cms\Model\Config\Source;
 
+use Magento\Cms\Model\Resource\Page\CollectionFactory;
+
 /**
  * Class Page
  */
@@ -16,25 +18,17 @@ class Page implements \Magento\Framework\Option\ArrayInterface
     protected $options;
 
     /**
-     * @var \Magento\Cms\Model\PageRepository
-     */
-    protected $pageRepository;
-
-    /**
-     * @var \Magento\Cms\Model\Resource\PageCriteria
+     * @var CollectionFactory
      */
-    protected $pageCriteriaFactory;
+    protected $collectionFactory;
 
     /**
-     * @param \Magento\Cms\Model\PageRepository $pageRepository
-     * @param \Magento\Cms\Model\Resource\PageCriteriaFactory $pageCriteriaFactory
+     * @param CollectionFactory $collectionFactory
      */
     public function __construct(
-        \Magento\Cms\Model\PageRepository $pageRepository,
-        \Magento\Cms\Model\Resource\PageCriteriaFactory $pageCriteriaFactory
+        CollectionFactory $collectionFactory
     ) {
-        $this->pageRepository = $pageRepository;
-        $this->pageCriteriaFactory = $pageCriteriaFactory;
+        $this->collectionFactory = $collectionFactory;
     }
 
     /**
@@ -45,7 +39,7 @@ class Page implements \Magento\Framework\Option\ArrayInterface
     public function toOptionArray()
     {
         if (!$this->options) {
-            $this->options = $this->pageRepository->getList($this->pageCriteriaFactory->create())->toOptionIdArray();
+            $this->options = $this->collectionFactory->create()->toOptionIdArray();
         }
         return $this->options;
     }
diff --git a/app/code/Magento/Cms/Model/DataSource/BlockCollection.php b/app/code/Magento/Cms/Model/DataSource/BlockCollection.php
deleted file mode 100644
index b63c604fcd6865a88fcb7d0fadc1a578ce59e163..0000000000000000000000000000000000000000
--- a/app/code/Magento/Cms/Model/DataSource/BlockCollection.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Cms\Model\DataSource;
-
-use Magento\Framework\Data\CollectionDataSourceInterface;
-use Magento\Cms\Model\Resource\BlockCriteria;
-use Magento\Cms\Model\BlockRepository;
-
-/**
- * CMS block collection data source
- *
- * Class BlockCollection
- */
-class BlockCollection extends BlockCriteria implements CollectionDataSourceInterface
-{
-    /**
-     * @var BlockRepository
-     */
-    protected $repository;
-
-    /**
-     * @param BlockRepository $repository
-     * @param string $mapper
-     */
-    public function __construct(BlockRepository $repository, $mapper = '')
-    {
-        $this->repository = $repository;
-        $this->setFirstStoreFlag(true);
-        parent::__construct($mapper);
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function addFilter($name, $field, $condition = null, $type = 'public')
-    {
-        if ($field === 'store_id') {
-            $this->addStoreFilter($condition, false);
-        } else {
-            parent::addFilter($name, $field, $condition, $type);
-        }
-    }
-
-    /**
-     * @return \Magento\Cms\Model\Resource\Block\Collection
-     */
-    public function getResultCollection()
-    {
-        return $this->repository->getList($this);
-    }
-}
diff --git a/app/code/Magento/Cms/Model/DataSource/PageCollection.php b/app/code/Magento/Cms/Model/DataSource/PageCollection.php
deleted file mode 100644
index 74491d38aea4c6a72e70e6bba56596dba579103b..0000000000000000000000000000000000000000
--- a/app/code/Magento/Cms/Model/DataSource/PageCollection.php
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Cms\Model\DataSource;
-
-use Magento\Cms\Model\Resource\PageCriteria;
-use Magento\Framework\Data\CollectionDataSourceInterface;
-
-/**
- * CMS page collection data source
- *
- * Class PageCollection
- */
-class PageCollection extends PageCriteria implements CollectionDataSourceInterface
-{
-    /**
-     * @var \Magento\Cms\Model\PageRepository
-     */
-    protected $repository;
-
-    /**
-     * @param \Magento\Cms\Model\PageRepository $repository
-     * @param string $mapper
-     */
-    public function __construct(\Magento\Cms\Model\PageRepository $repository, $mapper = '')
-    {
-        $this->repository = $repository;
-        $this->setFirstStoreFlag(true);
-        parent::__construct($mapper);
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function addFilter($name, $field, $condition = null, $type = 'public')
-    {
-        if ($field === 'store_id') {
-            $this->addStoreFilter($condition, false);
-        } else {
-            parent::addFilter($name, $field, $condition, $type);
-        }
-    }
-
-    /**
-     * @return \Magento\Cms\Model\Resource\Page\Collection
-     */
-    public function getResultCollection()
-    {
-        return $this->repository->getList($this);
-    }
-
-    /**
-     * Add Criteria object
-     *
-     * @param \Magento\Cms\Model\Resource\PageCriteria $criteria
-     * @return void
-     */
-    public function addCriteria(\Magento\Cms\Model\Resource\PageCriteria $criteria)
-    {
-        $this->data[self::PART_CRITERIA_LIST]['list'][] = $criteria;
-    }
-}
diff --git a/app/code/Magento/Cms/Model/Page.php b/app/code/Magento/Cms/Model/Page.php
index d1693facd3e2180a190c88961455eb3dbe4f8ff8..fca4ecc84aa66052fc48af15edf6d9fac83aeb41 100644
--- a/app/code/Magento/Cms/Model/Page.php
+++ b/app/code/Magento/Cms/Model/Page.php
@@ -5,6 +5,7 @@
  */
 namespace Magento\Cms\Model;
 
+use Magento\Cms\Api\Data\PageInterface;
 use Magento\Framework\Object\IdentityInterface;
 
 /**
@@ -12,41 +13,9 @@ use Magento\Framework\Object\IdentityInterface;
  *
  * @method \Magento\Cms\Model\Resource\Page _getResource()
  * @method \Magento\Cms\Model\Resource\Page getResource()
- * @method \Magento\Cms\Model\Page setTitle(string $value)
- * @method string getPageLayout()
- * @method \Magento\Cms\Model\Page setPageLayout(string $value)
- * @method string getMetaKeywords()
- * @method \Magento\Cms\Model\Page setMetaKeywords(string $value)
- * @method string getMetaDescription()
- * @method \Magento\Cms\Model\Page setMetaDescription(string $value)
- * @method \Magento\Cms\Model\Page setIdentifier(string $value)
- * @method string getContentHeading()
- * @method \Magento\Cms\Model\Page setContentHeading(string $value)
- * @method string getContent()
- * @method \Magento\Cms\Model\Page setContent(string $value)
- * @method string getCreationTime()
- * @method \Magento\Cms\Model\Page setCreationTime(string $value)
- * @method string getUpdateTime()
- * @method \Magento\Cms\Model\Page setUpdateTime(string $value)
- * @method int getIsActive()
- * @method \Magento\Cms\Model\Page setIsActive(int $value)
- * @method int getSortOrder()
- * @method \Magento\Cms\Model\Page setSortOrder(int $value)
- * @method string getLayoutUpdateXml()
- * @method \Magento\Cms\Model\Page setLayoutUpdateXml(string $value)
- * @method string getCustomTheme()
- * @method \Magento\Cms\Model\Page setCustomTheme(string $value)
- * @method string getCustomPageLayout()
- * @method \Magento\Cms\Model\Page setCustomPageLayout(string $value)
- * @method string getCustomLayoutUpdateXml()
- * @method \Magento\Cms\Model\Page setCustomLayoutUpdateXml(string $value)
- * @method string getCustomThemeFrom()
- * @method \Magento\Cms\Model\Page setCustomThemeFrom(string $value)
- * @method string getCustomThemeTo()
- * @method \Magento\Cms\Model\Page setCustomThemeTo(string $value)
  * @method int[] getStores()
  */
-class Page extends \Magento\Framework\Model\AbstractModel implements IdentityInterface
+class Page extends \Magento\Framework\Model\AbstractModel implements PageInterface, IdentityInterface
 {
     /**
      * No route page id
@@ -60,14 +29,6 @@ class Page extends \Magento\Framework\Model\AbstractModel implements IdentityInt
     const STATUS_DISABLED = 0;
     /**#@-*/
 
-    /**#@+
-     * Data object constants
-     */
-    const PAGE_ID = 'page_id';
-    const IDENTIFIER = 'identifier';
-    const TITLE = 'title';
-    /**#@-*/
-
     /**
      * CMS page cache tag
      */
@@ -95,30 +56,6 @@ class Page extends \Magento\Framework\Model\AbstractModel implements IdentityInt
         $this->_init('Magento\Cms\Model\Resource\Page');
     }
 
-    /**
-     * @return int
-     */
-    public function getId()
-    {
-        return $this->_getData(self::PAGE_ID);
-    }
-
-    /**
-     * @return string
-     */
-    public function getIdentifier()
-    {
-        return (string) $this->_getData(self::IDENTIFIER);
-    }
-
-    /**
-     * @return string
-     */
-    public function getTitle()
-    {
-        return $this->_getData(self::TITLE);
-    }
-
     /**
      * Load object data
      *
@@ -177,4 +114,382 @@ class Page extends \Magento\Framework\Model\AbstractModel implements IdentityInt
     {
         return [self::CACHE_TAG . '_' . $this->getId()];
     }
+
+    /**
+     * Get ID
+     *
+     * @return int
+     */
+    public function getId()
+    {
+        return parent::getData(self::PAGE_ID);
+    }
+
+    /**
+     * Get identifier
+     *
+     * @return string
+     */
+    public function getIdentifier()
+    {
+        return $this->getData(self::IDENTIFIER);
+    }
+
+    /**
+     * Get title
+     *
+     * @return string
+     */
+    public function getTitle()
+    {
+        return $this->getData(self::TITLE);
+    }
+
+    /**
+     * Get page layout
+     *
+     * @return string
+     */
+    public function getPageLayout()
+    {
+        return $this->getData(self::PAGE_LAYOUT);
+    }
+
+    /**
+     * Get meta keywords
+     *
+     * @return string
+     */
+    public function getMetaKeywords()
+    {
+        return $this->getData(self::META_KEYWORDS);
+    }
+
+    /**
+     * Get meta description
+     *
+     * @return string
+     */
+    public function getMetaDescription()
+    {
+        return $this->getData(self::META_DESCRIPTION);
+    }
+
+    /**
+     * Get content heading
+     *
+     * @return string
+     */
+    public function getContentHeading()
+    {
+        return $this->getData(self::CONTENT_HEADING);
+    }
+
+    /**
+     * Get content
+     *
+     * @return string
+     */
+    public function getContent()
+    {
+        return $this->getData(self::CONTENT);
+    }
+
+    /**
+     * Get creation time
+     *
+     * @return string
+     */
+    public function getCreationTime()
+    {
+        return $this->getData(self::CREATION_TIME);
+    }
+
+    /**
+     * Get update time
+     *
+     * @return string
+     */
+    public function getUpdateTime()
+    {
+        return $this->getData(self::UPDATE_TIME);
+    }
+
+    /**
+     * Get sort order
+     *
+     * @return string
+     */
+    public function getSortOrder()
+    {
+        return $this->getData(self::SORT_ORDER);
+    }
+
+    /**
+     * Get layout update xml
+     *
+     * @return string
+     */
+    public function getLayoutUpdateXml()
+    {
+        return $this->getData(self::LAYOUT_UPDATE_XML);
+    }
+
+    /**
+     * Get custom theme
+     *
+     * @return string
+     */
+    public function getCustomTheme()
+    {
+        return $this->getData(self::CUSTOM_THEME);
+    }
+
+    /**
+     * Get custom root template
+     *
+     * @return string
+     */
+    public function getCustomRootTemplate()
+    {
+        return $this->getData(self::CUSTOM_ROOT_TEMPLATE);
+    }
+
+    /**
+     * Get custom layout update xml
+     *
+     * @return string
+     */
+    public function getCustomLayoutUpdateXml()
+    {
+        return $this->getData(self::CUSTOM_LAYOUT_UPDATE_XML);
+    }
+
+    /**
+     * Get custom theme from
+     *
+     * @return string
+     */
+    public function getCustomThemeFrom()
+    {
+        return $this->getData(self::CUSTOM_THEME_FROM);
+    }
+
+    /**
+     * Get custom theme to
+     *
+     * @return string
+     */
+    public function getCustomThemeTo()
+    {
+        return $this->getData(self::CUSTOM_THEME_TO);
+    }
+
+    /**
+     * Is active
+     *
+     * @return bool
+     */
+    public function isActive()
+    {
+        return (bool)$this->getData(self::IS_ACTIVE);
+    }
+
+    /**
+     * Set ID
+     *
+     * @param int $id
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setId($id)
+    {
+        return $this->setData(self::PAGE_ID, $id);
+    }
+
+    /**
+     * Set identifier
+     *
+     * @param string $identifier
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setIdentifier($identifier)
+    {
+        return $this->setData(self::IDENTIFIER, $identifier);
+    }
+
+    /**
+     * Set title
+     *
+     * @param string $title
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setTitle($title)
+    {
+        return $this->setData(self::TITLE, $title);
+    }
+
+    /**
+     * Set page layout
+     *
+     * @param string $pageLayout
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setPageLayout($pageLayout)
+    {
+        return $this->setData(self::PAGE_LAYOUT, $pageLayout);
+    }
+
+    /**
+     * Set meta keywords
+     *
+     * @param string $metaKeywords
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setMetaKeywords($metaKeywords)
+    {
+        return $this->setData(self::META_KEYWORDS, $metaKeywords);
+    }
+
+    /**
+     * Set meta description
+     *
+     * @param string $metaDescription
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setMetaDescription($metaDescription)
+    {
+        return $this->setData(self::META_DESCRIPTION, $metaDescription);
+    }
+
+    /**
+     * Set content heading
+     *
+     * @param string $contentHeading
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setContentHeading($contentHeading)
+    {
+        return $this->setData(self::CONTENT_HEADING, $contentHeading);
+    }
+
+    /**
+     * Set content
+     *
+     * @param string $content
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setContent($content)
+    {
+        return $this->setData(self::CONTENT, $content);
+    }
+
+    /**
+     * Set creation time
+     *
+     * @param string $creationTime
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setCreationTime($creationTime)
+    {
+        return $this->setData(self::CREATION_TIME, $creationTime);
+    }
+
+    /**
+     * Set update time
+     *
+     * @param string $updateTime
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setUpdateTime($updateTime)
+    {
+        return $this->setData(self::UPDATE_TIME, $updateTime);
+    }
+
+    /**
+     * Set sort order
+     *
+     * @param string $sortOrder
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setSortOrder($sortOrder)
+    {
+        return $this->setData(self::SORT_ORDER, $sortOrder);
+    }
+
+    /**
+     * Set layout update xml
+     *
+     * @param string $layoutUpdateXml
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setLayoutUpdateXml($layoutUpdateXml)
+    {
+        return $this->setData(self::LAYOUT_UPDATE_XML, $layoutUpdateXml);
+    }
+
+    /**
+     * Set custom theme
+     *
+     * @param string $customTheme
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setCustomTheme($customTheme)
+    {
+        return $this->setData(self::CUSTOM_THEME, $customTheme);
+    }
+
+    /**
+     * Set custom root template
+     *
+     * @param string $customRootTemplate
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setCustomRootTemplate($customRootTemplate)
+    {
+        return $this->setData(self::CUSTOM_ROOT_TEMPLATE, $customRootTemplate);
+    }
+
+    /**
+     * Set custom layout update xml
+     *
+     * @param string $customLayoutUpdateXml
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setCustomLayoutUpdateXml($customLayoutUpdateXml)
+    {
+        return $this->setData(self::CUSTOM_LAYOUT_UPDATE_XML, $customLayoutUpdateXml);
+    }
+
+    /**
+     * Set custom theme from
+     *
+     * @param string $customThemeFrom
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setCustomThemeFrom($customThemeFrom)
+    {
+        return $this->setData(self::CUSTOM_THEME_FROM, $customThemeFrom);
+    }
+
+    /**
+     * Set custom theme to
+     *
+     * @param string $customThemeTo
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setCustomThemeTo($customThemeTo)
+    {
+        return $this->setData(self::CUSTOM_THEME_TO, $customThemeTo);
+    }
+
+    /**
+     * Set is active
+     *
+     * @param int|bool $isActive
+     * @return \Magento\Cms\Api\Data\PageInterface
+     */
+    public function setIsActive($isActive)
+    {
+        return $this->setData(self::IS_ACTIVE, $isActive);
+    }
 }
diff --git a/app/code/Magento/Cms/Model/PageCriteriaInterface.php b/app/code/Magento/Cms/Model/PageCriteriaInterface.php
deleted file mode 100644
index 692fb97988f222d119b02fcf536bc01b656b3e21..0000000000000000000000000000000000000000
--- a/app/code/Magento/Cms/Model/PageCriteriaInterface.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Cms\Model;
-
-/**
- * Interface PageCriteriaInterface
- */
-interface PageCriteriaInterface extends \Magento\Framework\Api\CriteriaInterface
-{
-    /**
-     * Set first store flag
-     *
-     * @param bool $flag
-     * @return void
-     */
-    public function setFirstStoreFlag($flag = false);
-
-    /**
-     * Add filter by store
-     *
-     * @param int|\Magento\Store\Model\Store $store
-     * @param bool $withAdmin
-     * @return void
-     */
-    public function addStoreFilter($store, $withAdmin = true);
-}
diff --git a/app/code/Magento/Cms/Model/PageRepository.php b/app/code/Magento/Cms/Model/PageRepository.php
index 67815ec24adb01de14531640a2cdbeec49f2a471..82fbba3748d12cdb9dd26ec4dd0d62c9f6c50455 100644
--- a/app/code/Magento/Cms/Model/PageRepository.php
+++ b/app/code/Magento/Cms/Model/PageRepository.php
@@ -5,69 +5,82 @@
  */
 namespace Magento\Cms\Model;
 
+use Magento\Cms\Api\Data;
+use Magento\Cms\Api\PageRepositoryInterface;
+use Magento\Framework\Api\DataObjectHelper;
+use Magento\Framework\Api\SearchCriteriaInterface;
 use Magento\Framework\Exception\CouldNotDeleteException;
 use Magento\Framework\Exception\CouldNotSaveException;
 use Magento\Framework\Exception\NoSuchEntityException;
 
 /**
  * Class PageRepository
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
-class PageRepository
+class PageRepository implements PageRepositoryInterface
 {
     /**
-     * @var \Magento\Cms\Model\Resource\Page
+     * @var Resource\Page
      */
     protected $resource;
 
     /**
-     * @var \Magento\Cms\Model\PageFactory
+     * @var PageFactory
      */
     protected $pageFactory;
 
     /**
-     * @var \Magento\Cms\Model\Resource\Page\CollectionFactory
+     * @var Resource\Page\CollectionFactory
      */
     protected $pageCollectionFactory;
 
     /**
-     * @var \Magento\Framework\DB\QueryBuilderFactory
+     * @var Data\PageSearchResultsInterfaceFactory
      */
-    protected $queryBuilderFactory;
+    protected $searchResultsFactory;
 
     /**
-     * @var \Magento\Framework\DB\MapperFactory
+     * @var DataObjectHelper
      */
-    protected $mapperFactory;
+    protected $dataObjectHelper;
+
+    /**
+     * @var Data\PageInterfaceFactory
+     */
+    protected $dataPageFactory;
 
     /**
      * @param Resource\Page $resource
-     * @param \Magento\Cms\Model\PageFactory $pageFactory
-     * @param \Magento\Cms\Model\Resource\Page\CollectionFactory $pageCollectionFactory
-     * @param \Magento\Framework\DB\QueryBuilderFactory $queryBuilderFactory
-     * @param \Magento\Framework\DB\MapperFactory $mapperFactory
+     * @param PageFactory $pageFactory
+     * @param Data\PageInterfaceFactory $dataPageFactory
+     * @param Resource\Page\CollectionFactory $pageCollectionFactory
+     * @param Data\PageSearchResultsInterfaceFactory $searchResultsFactory
+     * @param DataObjectHelper $dataObjectHelper
      */
     public function __construct(
-        \Magento\Cms\Model\Resource\Page $resource,
-        \Magento\Cms\Model\PageFactory $pageFactory,
-        \Magento\Cms\Model\Resource\Page\CollectionFactory $pageCollectionFactory,
-        \Magento\Framework\DB\QueryBuilderFactory $queryBuilderFactory,
-        \Magento\Framework\DB\MapperFactory $mapperFactory
+        Resource\Page $resource,
+        PageFactory $pageFactory,
+        Data\PageInterfaceFactory $dataPageFactory,
+        Resource\Page\CollectionFactory $pageCollectionFactory,
+        Data\PageSearchResultsInterfaceFactory $searchResultsFactory,
+        DataObjectHelper $dataObjectHelper
     ) {
         $this->resource = $resource;
         $this->pageFactory = $pageFactory;
         $this->pageCollectionFactory = $pageCollectionFactory;
-        $this->queryBuilderFactory = $queryBuilderFactory;
-        $this->mapperFactory = $mapperFactory;
+        $this->searchResultsFactory = $searchResultsFactory;
+        $this->dataObjectHelper = $dataObjectHelper;
+        $this->dataPageFactory = $dataPageFactory;
     }
 
     /**
      * Save Page data
      *
-     * @param \Magento\Cms\Model\Page $page
-     * @return \Magento\Cms\Model\Page
+     * @param Data\PageInterface $page
+     * @return Page
      * @throws CouldNotSaveException
      */
-    public function save(\Magento\Cms\Model\Page $page)
+    public function save(Data\PageInterface $page)
     {
         try {
             $this->resource->save($page);
@@ -81,10 +94,10 @@ class PageRepository
      * Load Page data by given Page Identity
      *
      * @param string $pageId
-     * @return \Magento\Cms\Model\Page
+     * @return Page
      * @throws \Magento\Framework\Exception\NoSuchEntityException
      */
-    public function get($pageId)
+    public function getById($pageId)
     {
         $page = $this->pageFactory->create();
         $this->resource->load($page, $pageId);
@@ -97,27 +110,65 @@ class PageRepository
     /**
      * Load Page data collection by given search criteria
      *
-     * @param \Magento\Cms\Model\PageCriteriaInterface $criteria
-     * @return \Magento\Cms\Model\Resource\Page\Collection
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     * @param SearchCriteriaInterface $criteria
+     * @return Resource\Page\Collection
      */
-    public function getList(\Magento\Cms\Model\PageCriteriaInterface $criteria)
+    public function getList(SearchCriteriaInterface $criteria)
     {
-        $queryBuilder = $this->queryBuilderFactory->create();
-        $queryBuilder->setCriteria($criteria);
-        $queryBuilder->setResource($this->resource);
-        $query = $queryBuilder->create();
-        $collection = $this->pageCollectionFactory->create(['query' => $query]);
-        return $collection;
+        $searchResults = $this->searchResultsFactory->create();
+        $searchResults->setSearchCriteria($criteria);
+
+        $collection = $this->pageCollectionFactory->create();
+        foreach ($criteria->getFilterGroups() as $filterGroup) {
+            $fields = [];
+            $conditions = [];
+            foreach ($filterGroup->getFilters() as $filter) {
+                if ($filter->getField() === 'store_id') {
+                    $collection->addStoreFilter($filter->getValue(), false);
+                    continue;
+                }
+                $condition = $filter->getConditionType() ?: 'eq';
+                $fields[] = ['attribute' => $filter->getField(), $condition => $filter->getValue()];
+            }
+            if ($fields) {
+                $collection->addFieldToFilter($fields, $conditions);
+            }
+        }
+        $searchResults->setTotalCount($collection->getSize());
+        $sortOrders = $criteria->getSortOrders();
+        if ($sortOrders) {
+            foreach ($sortOrders as $sortOrder) {
+                $collection->addOrder(
+                    $sortOrder->getField(),
+                    ($sortOrder->getDirection() == SearchCriteriaInterface::SORT_ASC) ? 'ASC' : 'DESC'
+                );
+            }
+        }
+        $collection->setCurPage($criteria->getCurrentPage());
+        $collection->setPageSize($criteria->getPageSize());
+        $pages = [];
+        /** @var Page $pageModel */
+        foreach ($collection as $pageModel) {
+            $pages[] = $this->dataObjectHelper->populateWithArray(
+                $this->dataPageFactory->create(),
+                $pageModel->getData(),
+                'Magento\Cms\Api\Data\PageInterface'
+            );
+        }
+        $searchResults->setItems($pages);
+        return $searchResults;
     }
 
     /**
      * Delete Page
      *
-     * @param \Magento\Cms\Model\Page $page
+     * @param Data\PageInterface $page
      * @return bool
-     * @throws \Magento\Framework\Exception\CouldNotDeleteException
+     * @throws CouldNotDeleteException
      */
-    public function delete(\Magento\Cms\Model\Page $page)
+    public function delete(Data\PageInterface $page)
     {
         try {
             $this->resource->delete($page);
@@ -132,11 +183,11 @@ class PageRepository
      *
      * @param string $pageId
      * @return bool
-     * @throws \Magento\Framework\Exception\CouldNotDeleteException
-     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     * @throws CouldNotDeleteException
+     * @throws NoSuchEntityException
      */
     public function deleteById($pageId)
     {
-        return $this->delete($this->get($pageId));
+        return $this->delete($this->getById($pageId));
     }
 }
diff --git a/app/code/Magento/Cms/Model/Resource/Block/Collection.php b/app/code/Magento/Cms/Model/Resource/Block/Collection.php
index b6e0b2db406ee0cfd33a7fffe3b5494c21f4d508..3898607f31ed81b2ebe958e33eb56eeb243660df 100644
--- a/app/code/Magento/Cms/Model/Resource/Block/Collection.php
+++ b/app/code/Magento/Cms/Model/Resource/Block/Collection.php
@@ -1,27 +1,117 @@
 <?php
 /**
+ * Cms block grid collection
+ *
  * Copyright © 2015 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
 namespace Magento\Cms\Model\Resource\Block;
 
-use Magento\Cms\Model\Resource\AbstractCollection;
-
 /**
- * CMS block collection
- *
  * Class Collection
  */
-class Collection extends AbstractCollection
+class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
 {
     /**
+     * @return \Magento\Cms\Model\Resource\Block\Collection
+     */
+    protected function _afterLoad()
+    {
+        $this->walk('afterLoad');
+        parent::_afterLoad();
+    }
+
+    /**
+     * @param string|array $field
+     * @param string|int|array|null $condition
+     * @return \Magento\Cms\Model\Resource\Block\Collection
+     */
+    public function addFieldToFilter($field, $condition = null)
+    {
+        if ($field == 'store_id') {
+            return $this->addStoreFilter($condition, false);
+        }
+        return parent::addFieldToFilter($field, $condition);
+    }
+
+    /**
+     * Define resource model
+     *
+     * @return void
+     */
+    protected function _construct()
+    {
+        $this->_init('Magento\Cms\Model\Block', 'Magento\Cms\Model\Resource\Block');
+        $this->_map['fields']['store'] = 'store_table.store_id';
+    }
+
+    /**
+     * Returns pairs block_id - title
+     *
+     * @return array
+     */
+    public function toOptionArray()
+    {
+        return $this->_toOptionArray('block_id', 'title');
+    }
+
+    /**
+     * Add filter by store
+     *
+     * @param int|\Magento\Store\Model\Store $store
+     * @param bool $withAdmin
+     * @return $this
+     */
+    public function addStoreFilter($store, $withAdmin = true)
+    {
+        if ($store instanceof \Magento\Store\Model\Store) {
+            $store = [$store->getId()];
+        }
+
+        if (!is_array($store)) {
+            $store = [$store];
+        }
+
+        if ($withAdmin) {
+            $store[] = \Magento\Store\Model\Store::DEFAULT_STORE_ID;
+        }
+
+        $this->addFilter('store', ['in' => $store], 'public');
+
+        return $this;
+    }
+
+    /**
+     * Get SQL for get record count.
+     * Extra GROUP BY strip added.
+     *
+     * @return \Magento\Framework\DB\Select
+     */
+    public function getSelectCountSql()
+    {
+        $countSelect = parent::getSelectCountSql();
+
+        $countSelect->reset(\Zend_Db_Select::GROUP);
+
+        return $countSelect;
+    }
+
+    /**
+     * Join store relation table if there is store filter
+     *
      * @return void
      */
-    protected function init()
+    protected function _renderFiltersBefore()
     {
-        $this->setDataInterfaceName('Magento\Cms\Model\Block');
-        $this->storeTableName = 'cms_block_store';
-        $this->linkFieldName = 'block_id';
-        parent::init();
+        if ($this->getFilter('store')) {
+            $this->getSelect()->join(
+                ['store_table' => $this->getTable('cms_block_store')],
+                'main_table.block_id = store_table.block_id',
+                []
+            )->group(
+                'main_table.block_id'
+            );
+        }
+        parent::_renderFiltersBefore();
     }
 }
diff --git a/app/code/Magento/Cms/Model/Resource/Block/Grid/Collection.php b/app/code/Magento/Cms/Model/Resource/Block/Grid/Collection.php
deleted file mode 100644
index 50b5433e4fc9dc0a2b83e4cbd93ce89b3ab450e7..0000000000000000000000000000000000000000
--- a/app/code/Magento/Cms/Model/Resource/Block/Grid/Collection.php
+++ /dev/null
@@ -1,117 +0,0 @@
-<?php
-/**
- * Cms block grid collection
- *
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Cms\Model\Resource\Block\Grid;
-
-/**
- * Class Collection
- */
-class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
-{
-    /**
-     * @return \Magento\Cms\Model\Resource\Block\Grid\Collection
-     */
-    protected function _afterLoad()
-    {
-        $this->walk('afterLoad');
-        parent::_afterLoad();
-    }
-
-    /**
-     * @param string|array $field
-     * @param string|int|array|null $condition
-     * @return \Magento\Cms\Model\Resource\Block\Grid\Collection
-     */
-    public function addFieldToFilter($field, $condition = null)
-    {
-        if ($field == 'store_id') {
-            return $this->addStoreFilter($condition, false);
-        }
-        return parent::addFieldToFilter($field, $condition);
-    }
-
-    /**
-     * Define resource model
-     *
-     * @return void
-     */
-    protected function _construct()
-    {
-        $this->_init('Magento\Cms\Model\Block', 'Magento\Cms\Model\Resource\Block');
-        $this->_map['fields']['store'] = 'store_table.store_id';
-    }
-
-    /**
-     * Returns pairs block_id - title
-     *
-     * @return array
-     */
-    public function toOptionArray()
-    {
-        return $this->_toOptionArray('block_id', 'title');
-    }
-
-    /**
-     * Add filter by store
-     *
-     * @param int|\Magento\Store\Model\Store $store
-     * @param bool $withAdmin
-     * @return $this
-     */
-    public function addStoreFilter($store, $withAdmin = true)
-    {
-        if ($store instanceof \Magento\Store\Model\Store) {
-            $store = [$store->getId()];
-        }
-
-        if (!is_array($store)) {
-            $store = [$store];
-        }
-
-        if ($withAdmin) {
-            $store[] = \Magento\Store\Model\Store::DEFAULT_STORE_ID;
-        }
-
-        $this->addFilter('store', ['in' => $store], 'public');
-
-        return $this;
-    }
-
-    /**
-     * Get SQL for get record count.
-     * Extra GROUP BY strip added.
-     *
-     * @return \Magento\Framework\DB\Select
-     */
-    public function getSelectCountSql()
-    {
-        $countSelect = parent::getSelectCountSql();
-
-        $countSelect->reset(\Zend_Db_Select::GROUP);
-
-        return $countSelect;
-    }
-
-    /**
-     * Join store relation table if there is store filter
-     *
-     * @return void
-     */
-    protected function _renderFiltersBefore()
-    {
-        if ($this->getFilter('store')) {
-            $this->getSelect()->join(
-                ['store_table' => $this->getTable('cms_block_store')],
-                'main_table.block_id = store_table.block_id',
-                []
-            )->group(
-                'main_table.block_id'
-            );
-        }
-        parent::_renderFiltersBefore();
-    }
-}
diff --git a/app/code/Magento/Cms/Model/Resource/BlockCriteria.php b/app/code/Magento/Cms/Model/Resource/BlockCriteria.php
deleted file mode 100644
index e10c0c0c15d612b6b15e20e6ddc7a194e3b9bbfa..0000000000000000000000000000000000000000
--- a/app/code/Magento/Cms/Model/Resource/BlockCriteria.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Cms\Model\Resource;
-
-use Magento\Cms\Model\BlockCriteriaInterface;
-
-/**
- * Class BlockCriteria
- */
-class BlockCriteria extends CmsAbstractCriteria implements BlockCriteriaInterface
-{
-    /**
-     * @param string $mapper
-     */
-    public function __construct($mapper = '')
-    {
-        $this->mapperInterfaceName = $mapper ?: 'Magento\Cms\Model\Resource\BlockCriteriaMapper';
-    }
-}
diff --git a/app/code/Magento/Cms/Model/Resource/BlockCriteriaMapper.php b/app/code/Magento/Cms/Model/Resource/BlockCriteriaMapper.php
deleted file mode 100644
index cfa339ad26232172404adb67094aa1ba90010b58..0000000000000000000000000000000000000000
--- a/app/code/Magento/Cms/Model/Resource/BlockCriteriaMapper.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Cms\Model\Resource;
-
-/**
- * Class BlockCriteriaMapper
- */
-class BlockCriteriaMapper extends CmsCriteriaMapper
-{
-    /**
-     * @inheritdoc
-     */
-    protected function init()
-    {
-        $this->storeTableName = 'cms_block_store';
-        $this->linkFieldName = 'block_id';
-        $this->initResource('Magento\Cms\Model\Resource\Block');
-        parent::init();
-    }
-}
diff --git a/app/code/Magento/Cms/Model/Resource/CmsAbstractCriteria.php b/app/code/Magento/Cms/Model/Resource/CmsAbstractCriteria.php
deleted file mode 100644
index 88068299f8b9b9b68db949d2de672268827f35b6..0000000000000000000000000000000000000000
--- a/app/code/Magento/Cms/Model/Resource/CmsAbstractCriteria.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Cms\Model\Resource;
-
-use Magento\Framework\Data\AbstractCriteria;
-
-/**
- * Class CmsAbstractCriteria
- */
-class CmsAbstractCriteria extends AbstractCriteria
-{
-    /**
-     * @inheritdoc
-     */
-    public function setFirstStoreFlag($flag = false)
-    {
-        $this->data['first_store_flag'] = $flag;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function addStoreFilter($store, $withAdmin = true)
-    {
-        $this->data['store_filter'] = [$store, $withAdmin];
-    }
-}
diff --git a/app/code/Magento/Cms/Model/Resource/CmsCriteriaMapper.php b/app/code/Magento/Cms/Model/Resource/CmsCriteriaMapper.php
deleted file mode 100644
index ffac24c942d62253aed5c41b61564ef26d0fdc3e..0000000000000000000000000000000000000000
--- a/app/code/Magento/Cms/Model/Resource/CmsCriteriaMapper.php
+++ /dev/null
@@ -1,79 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Cms\Model\Resource;
-
-use Magento\Framework\DB\GenericMapper;
-
-/**
- * Class CmsCriteriaMapper
- */
-class CmsCriteriaMapper extends GenericMapper
-{
-    /**
-     * Table which links CMS entity to stores
-     *
-     * @var string
-     */
-    protected $storeTableName;
-
-    /**
-     * @var string
-     */
-    protected $linkFieldName;
-
-    /**
-     * @inheritdoc
-     */
-    protected function init()
-    {
-        $this->map['fields']['store'] = 'store_table.store_id';
-        $this->map['fields']['store_id'] = 'store_table.store_id';
-    }
-
-    /**
-     * Set first store flag
-     *
-     * @param bool $flag
-     * @return void
-     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
-     */
-    public function mapFirstStoreFlag($flag)
-    {
-        // do nothing since handled in collection afterLoad
-    }
-
-    /**
-     * Add filter by store
-     *
-     * @param int|\Magento\Store\Model\Store $store
-     * @param bool $withAdmin
-     * @return void
-     */
-    public function mapStoreFilter($store, $withAdmin)
-    {
-        $this->getSelect()->join(
-            ['store_table' => $this->getTable($this->storeTableName)],
-            "main_table.{$this->linkFieldName} = store_table.{$this->linkFieldName}",
-            []
-        )->group("main_table.{$this->linkFieldName}");
-        if (!is_array($store)) {
-            if ($store instanceof \Magento\Store\Model\Store) {
-                $store = [$store->getId()];
-            } else {
-                $store = [$store];
-            }
-        }
-        if ($withAdmin) {
-            $store[] = \Magento\Store\Model\Store::DEFAULT_STORE_ID;
-        }
-        $field = $this->getMappedField('store');
-        $this->select->where(
-            $this->getConditionSql($field, ['in' => $store]),
-            null,
-            \Magento\Framework\DB\Select::TYPE_CONDITION
-        );
-    }
-}
diff --git a/app/code/Magento/Cms/Model/Resource/Page/Collection.php b/app/code/Magento/Cms/Model/Resource/Page/Collection.php
index 69dc4cfd7558d53b761aa54b03781bac30a3a666..2b8943acb57a50f1e1dba0c87c6f44649d71ebca 100644
--- a/app/code/Magento/Cms/Model/Resource/Page/Collection.php
+++ b/app/code/Magento/Cms/Model/Resource/Page/Collection.php
@@ -5,131 +5,212 @@
  */
 namespace Magento\Cms\Model\Resource\Page;
 
-use Magento\Framework\Data\AbstractSearchResult;
-use Magento\Framework\Data\Collection\EntityFactoryInterface;
-use Magento\Framework\Data\SearchResultIteratorFactory;
-use Magento\Framework\DB\QueryInterface;
-use Magento\Framework\Event\ManagerInterface;
-use Magento\Store\Model\StoreManagerInterface;
-use Magento\Framework\Data\SearchResultProcessorFactory;
-use Magento\Framework\Data\SearchResultProcessor;
-
 /**
  * CMS page collection
+ *
+ * Class Collection
  */
-class Collection extends AbstractSearchResult
+class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
 {
     /**
-     * @var StoreManagerInterface
+     * Load data for preview flag
+     *
+     * @var bool
      */
-    protected $storeManager;
+    protected $_previewFlag;
 
     /**
-     * @var SearchResultProcessor
+     * Store manager
+     *
+     * @var \Magento\Store\Model\StoreManagerInterface
      */
-    protected $searchResultProcessor;
+    protected $_storeManager;
 
     /**
-     * @param QueryInterface $query
-     * @param EntityFactoryInterface $entityFactory
-     * @param ManagerInterface $eventManager
-     * @param SearchResultIteratorFactory $resultIteratorFactory
+     * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory
+     * @param \Psr\Log\LoggerInterface $logger
+     * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
+     * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
-     * @param SearchResultProcessorFactory $searchResultProcessorFactory
+     * @param mixed $connection
+     * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
      */
     public function __construct(
-        QueryInterface $query,
-        EntityFactoryInterface $entityFactory,
-        ManagerInterface $eventManager,
-        SearchResultIteratorFactory $resultIteratorFactory,
-        StoreManagerInterface $storeManager,
-        SearchResultProcessorFactory $searchResultProcessorFactory
+        \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
+        \Psr\Log\LoggerInterface $logger,
+        \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
+        \Magento\Framework\Event\ManagerInterface $eventManager,
+        \Magento\Store\Model\StoreManagerInterface $storeManager,
+        $connection = null,
+        \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null
     ) {
-        $this->storeManager = $storeManager;
-        $this->searchResultProcessor = $searchResultProcessorFactory->create($this);
-        parent::__construct($query, $entityFactory, $eventManager, $resultIteratorFactory);
+        parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
+        $this->_storeManager = $storeManager;
     }
 
     /**
+     * Define resource model
+     *
      * @return void
      */
-    protected function init()
+    protected function _construct()
     {
-        $this->setDataInterfaceName('Magento\Cms\Model\Page');
-        $this->query->addCountSqlSkipPart(\Zend_Db_Select::GROUP, true);
-        $this->storeTableName = 'cms_page_store';
-        $this->linkFieldName = 'page_id';
+        $this->_init('Magento\Cms\Model\Page', 'Magento\Cms\Model\Resource\Page');
+        $this->_map['fields']['page_id'] = 'main_table.page_id';
+        $this->_map['fields']['store'] = 'store_table.store_id';
     }
 
     /**
+     * Returns pairs identifier - title for unique identifiers
+     * and pairs identifier|page_id - title for non-unique after first
+     *
      * @return array
      */
     public function toOptionIdArray()
     {
         $res = [];
         $existingIdentifiers = [];
-        foreach ($this->getItems() as $item) {
-            /** @var PageInterface $item */
-            $identifier = $item->getIdentifier();
+        foreach ($this as $item) {
+            $identifier = $item->getData('identifier');
 
             $data['value'] = $identifier;
-            $data['label'] = $item->getTitle();
+            $data['label'] = $item->getData('title');
 
             if (in_array($identifier, $existingIdentifiers)) {
-                $data['value'] .= '|' . $item->getPageId();
+                $data['value'] .= '|' . $item->getData('page_id');
             } else {
                 $existingIdentifiers[] = $identifier;
             }
+
             $res[] = $data;
         }
+
         return $res;
     }
 
     /**
-     * @deprecated
-     * @return void
+     * Set first store flag
+     *
+     * @param bool $flag
+     * @return $this
+     */
+    public function setFirstStoreFlag($flag = false)
+    {
+        $this->_previewFlag = $flag;
+        return $this;
+    }
+
+    /**
+     * Add field filter to collection
+     *
+     * @param string|array $field
+     * @param string|int|array|null $condition
+     * @return \Magento\Cms\Model\Resource\Block\Collection
+     */
+    public function addFieldToFilter($field, $condition = null)
+    {
+        if ($field === 'store_id') {
+            return $this->addStoreFilter($condition, false);
+        }
+
+        return parent::addFieldToFilter($field, $condition);
+    }
+
+    /**
+     * Add filter by store
+     *
+     * @param int|\Magento\Store\Model\Store $store
+     * @param bool $withAdmin
+     * @return $this
      */
-    public function addStoreFilter()
+    public function addStoreFilter($store, $withAdmin = true)
     {
-        //
+        if (!$this->getFlag('store_filter_added')) {
+            if ($store instanceof \Magento\Store\Model\Store) {
+                $store = [$store->getId()];
+            }
+
+            if (!is_array($store)) {
+                $store = [$store];
+            }
+
+            if ($withAdmin) {
+                $store[] = \Magento\Store\Model\Store::DEFAULT_STORE_ID;
+            }
+
+            $this->addFilter('store', ['in' => $store], 'public');
+        }
+        return $this;
     }
 
     /**
      * Perform operations after collection load
      *
-     * @return void
+     * @return $this
      */
-    protected function afterLoad()
+    protected function _afterLoad()
     {
-        if ($this->getSearchCriteria()->getPart('first_store_flag')) {
-            $items = $this->searchResultProcessor->getColumnValues('page_id');
-
-            $connection = $this->getQuery()->getConnection();
-            $resource = $this->getQuery()->getResource();
-            if (count($items)) {
-                $select = $connection->select()->from(['cps' => $resource->getTable('cms_page_store')])
-                    ->where('cps.page_id IN (?)', $items);
-                if ($result = $connection->fetchPairs($select)) {
-                    foreach ($this->getItems() as $item) {
-                        /** @var PageInterface $item */
-                        if (!isset($result[$item->getPageId()])) {
-                            continue;
-                        }
-                        if ($result[$item->getPageId()] == 0) {
-                            $stores = $this->storeManager->getStores(false, true);
-                            $storeId = current($stores)->getId();
-                            $storeCode = key($stores);
-                        } else {
-                            $storeId = $result[$item->getPageId()];
-                            $storeCode = $this->storeManager->getStore($storeId)->getCode();
-                        }
-                        $item->setData('_first_store_id', $storeId);
-                        $item->setData('store_code', $storeCode);
-                        $item->setData('store_id', [$result[$item->getPageId()]]);
+        $items = $this->getColumnValues('page_id');
+        if (count($items)) {
+            $connection = $this->getConnection();
+            $select = $connection->select()->from(['cps' => $this->getTable('cms_page_store')])
+                ->where('cps.page_id IN (?)', $items);
+            $result = $connection->fetchPairs($select);
+            if ($result) {
+                foreach ($this as $item) {
+                    $pageId = $item->getData('page_id');
+                    if (!isset($result[$pageId])) {
+                        continue;
+                    }
+                    if ($result[$pageId] == 0) {
+                        $stores = $this->_storeManager->getStores(false, true);
+                        $storeId = current($stores)->getId();
+                        $storeCode = key($stores);
+                    } else {
+                        $storeId = $result[$item->getData('page_id')];
+                        $storeCode = $this->_storeManager->getStore($storeId)->getCode();
                     }
+                    $item->setData('_first_store_id', $storeId);
+                    $item->setData('store_code', $storeCode);
+                    $item->setData('store_id', [$result[$pageId]]);
                 }
             }
         }
-        parent::afterLoad();
+
+        $this->_previewFlag = false;
+        return parent::_afterLoad();
+    }
+
+    /**
+     * Join store relation table if there is store filter
+     *
+     * @return void
+     */
+    protected function _renderFiltersBefore()
+    {
+        if ($this->getFilter('store')) {
+            $this->getSelect()->join(
+                ['store_table' => $this->getTable('cms_page_store')],
+                'main_table.page_id = store_table.page_id',
+                []
+            )->group(
+                'main_table.page_id'
+            );
+        }
+        parent::_renderFiltersBefore();
+    }
+
+    /**
+     * Get SQL for get record count.
+     * Extra GROUP BY strip added.
+     *
+     * @return \Magento\Framework\DB\Select
+     */
+    public function getSelectCountSql()
+    {
+        $countSelect = parent::getSelectCountSql();
+        $countSelect->reset(\Zend_Db_Select::GROUP);
+
+        return $countSelect;
     }
 }
diff --git a/app/code/Magento/Cms/Model/Resource/Page/Grid/Collection.php b/app/code/Magento/Cms/Model/Resource/Page/Grid/Collection.php
deleted file mode 100644
index 41402e0ed343f197fa58b3f10d6bf55bf302fcdc..0000000000000000000000000000000000000000
--- a/app/code/Magento/Cms/Model/Resource/Page/Grid/Collection.php
+++ /dev/null
@@ -1,216 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Cms\Model\Resource\Page\Grid;
-
-/**
- * CMS page collection
- *
- * Class Collection
- */
-class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
-{
-    /**
-     * Load data for preview flag
-     *
-     * @var bool
-     */
-    protected $_previewFlag;
-
-    /**
-     * Store manager
-     *
-     * @var \Magento\Store\Model\StoreManagerInterface
-     */
-    protected $_storeManager;
-
-    /**
-     * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory
-     * @param \Psr\Log\LoggerInterface $logger
-     * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
-     * @param \Magento\Framework\Event\ManagerInterface $eventManager
-     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
-     * @param mixed $connection
-     * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
-     */
-    public function __construct(
-        \Magento\Framework\Data\Collection\EntityFactory $entityFactory,
-        \Psr\Log\LoggerInterface $logger,
-        \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
-        \Magento\Framework\Event\ManagerInterface $eventManager,
-        \Magento\Store\Model\StoreManagerInterface $storeManager,
-        $connection = null,
-        \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null
-    ) {
-        parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
-        $this->_storeManager = $storeManager;
-    }
-
-    /**
-     * Define resource model
-     *
-     * @return void
-     */
-    protected function _construct()
-    {
-        $this->_init('Magento\Cms\Model\Page', 'Magento\Cms\Model\Resource\Page');
-        $this->_map['fields']['page_id'] = 'main_table.page_id';
-        $this->_map['fields']['store'] = 'store_table.store_id';
-    }
-
-    /**
-     * Returns pairs identifier - title for unique identifiers
-     * and pairs identifier|page_id - title for non-unique after first
-     *
-     * @return array
-     */
-    public function toOptionIdArray()
-    {
-        $res = [];
-        $existingIdentifiers = [];
-        foreach ($this as $item) {
-            $identifier = $item->getData('identifier');
-
-            $data['value'] = $identifier;
-            $data['label'] = $item->getData('title');
-
-            if (in_array($identifier, $existingIdentifiers)) {
-                $data['value'] .= '|' . $item->getData('page_id');
-            } else {
-                $existingIdentifiers[] = $identifier;
-            }
-
-            $res[] = $data;
-        }
-
-        return $res;
-    }
-
-    /**
-     * Set first store flag
-     *
-     * @param bool $flag
-     * @return $this
-     */
-    public function setFirstStoreFlag($flag = false)
-    {
-        $this->_previewFlag = $flag;
-        return $this;
-    }
-
-    /**
-     * Add field filter to collection
-     *
-     * @param string|array $field
-     * @param string|int|array|null $condition
-     * @return \Magento\Cms\Model\Resource\Block\Grid\Collection
-     */
-    public function addFieldToFilter($field, $condition = null)
-    {
-        if ($field === 'store_id') {
-            return $this->addStoreFilter($condition, false);
-        }
-
-        return parent::addFieldToFilter($field, $condition);
-    }
-
-    /**
-     * Add filter by store
-     *
-     * @param int|\Magento\Store\Model\Store $store
-     * @param bool $withAdmin
-     * @return $this
-     */
-    public function addStoreFilter($store, $withAdmin = true)
-    {
-        if (!$this->getFlag('store_filter_added')) {
-            if ($store instanceof \Magento\Store\Model\Store) {
-                $store = [$store->getId()];
-            }
-
-            if (!is_array($store)) {
-                $store = [$store];
-            }
-
-            if ($withAdmin) {
-                $store[] = \Magento\Store\Model\Store::DEFAULT_STORE_ID;
-            }
-
-            $this->addFilter('store', ['in' => $store], 'public');
-        }
-        return $this;
-    }
-
-    /**
-     * Perform operations after collection load
-     *
-     * @return $this
-     */
-    protected function _afterLoad()
-    {
-        $items = $this->getColumnValues('page_id');
-        if (count($items)) {
-            $connection = $this->getConnection();
-            $select = $connection->select()->from(['cps' => $this->getTable('cms_page_store')])
-                ->where('cps.page_id IN (?)', $items);
-            $result = $connection->fetchPairs($select);
-            if ($result) {
-                foreach ($this as $item) {
-                    $pageId = $item->getData('page_id');
-                    if (!isset($result[$pageId])) {
-                        continue;
-                    }
-                    if ($result[$pageId] == 0) {
-                        $stores = $this->_storeManager->getStores(false, true);
-                        $storeId = current($stores)->getId();
-                        $storeCode = key($stores);
-                    } else {
-                        $storeId = $result[$item->getData('page_id')];
-                        $storeCode = $this->_storeManager->getStore($storeId)->getCode();
-                    }
-                    $item->setData('_first_store_id', $storeId);
-                    $item->setData('store_code', $storeCode);
-                    $item->setData('store_id', [$result[$pageId]]);
-                }
-            }
-        }
-
-        $this->_previewFlag = false;
-        return parent::_afterLoad();
-    }
-
-    /**
-     * Join store relation table if there is store filter
-     *
-     * @return void
-     */
-    protected function _renderFiltersBefore()
-    {
-        if ($this->getFilter('store')) {
-            $this->getSelect()->join(
-                ['store_table' => $this->getTable('cms_page_store')],
-                'main_table.page_id = store_table.page_id',
-                []
-            )->group(
-                'main_table.page_id'
-            );
-        }
-        parent::_renderFiltersBefore();
-    }
-
-    /**
-     * Get SQL for get record count.
-     * Extra GROUP BY strip added.
-     *
-     * @return \Magento\Framework\DB\Select
-     */
-    public function getSelectCountSql()
-    {
-        $countSelect = parent::getSelectCountSql();
-        $countSelect->reset(\Zend_Db_Select::GROUP);
-
-        return $countSelect;
-    }
-}
diff --git a/app/code/Magento/Cms/Model/Resource/PageCriteria.php b/app/code/Magento/Cms/Model/Resource/PageCriteria.php
deleted file mode 100644
index 87cf04da8372198db34367c3f06424ac7b045efc..0000000000000000000000000000000000000000
--- a/app/code/Magento/Cms/Model/Resource/PageCriteria.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Cms\Model\Resource;
-
-use Magento\Cms\Model\PageCriteriaInterface;
-
-/**
- * Class PageCriteria
- */
-class PageCriteria extends CmsAbstractCriteria implements PageCriteriaInterface
-{
-    /**
-     * @param string $mapper
-     */
-    public function __construct($mapper = '')
-    {
-        $this->mapperInterfaceName = $mapper ?: 'Magento\Cms\Model\Resource\PageCriteriaMapper';
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function setFirstStoreFlag($flag = false)
-    {
-        $this->data['first_store_flag'] = $flag;
-        return true;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function addStoreFilter($store, $withAdmin = true)
-    {
-        $this->data['store_filter'] = [$store, $withAdmin];
-        return true;
-    }
-
-    /**
-     * Add Criteria object
-     *
-     * @param \Magento\Cms\Model\Resource\PageCriteria $criteria
-     * @return bool
-     */
-    public function addCriteria(\Magento\Cms\Model\Resource\PageCriteria $criteria)
-    {
-        $this->data[self::PART_CRITERIA_LIST]['list'][] = $criteria;
-        return true;
-    }
-}
diff --git a/app/code/Magento/Cms/Model/Resource/PageCriteriaMapper.php b/app/code/Magento/Cms/Model/Resource/PageCriteriaMapper.php
deleted file mode 100644
index 2c1aa20b396eacf22c2fdc10224e1e97ccccd8a6..0000000000000000000000000000000000000000
--- a/app/code/Magento/Cms/Model/Resource/PageCriteriaMapper.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Cms\Model\Resource;
-
-/**
- * Class PageCriteriaMapper
- */
-class PageCriteriaMapper extends CmsCriteriaMapper
-{
-    /**
-     * @inheritdoc
-     */
-    protected function init()
-    {
-        $this->storeTableName = 'cms_page_store';
-        $this->linkFieldName = 'page_id';
-        $this->initResource('Magento\Cms\Model\Resource\Page');
-        parent::init();
-    }
-}
diff --git a/app/code/Magento/Cms/Test/Unit/Model/BlockRepositoryTest.php b/app/code/Magento/Cms/Test/Unit/Model/BlockRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e5c3c9dd155437c9ff54c4a7e3e3312096bfea88
--- /dev/null
+++ b/app/code/Magento/Cms/Test/Unit/Model/BlockRepositoryTest.php
@@ -0,0 +1,300 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Cms\Test\Unit\Model;
+
+use Magento\Cms\Model\BlockRepository;
+use Magento\Framework\Api\SearchCriteriaInterface;
+
+/**
+ * Test for Magento\Cms\Model\BlockRepository
+ */
+class BlockRepositoryTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var BlockRepository
+     */
+    protected $repository;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Cms\Model\Resource\Block
+     */
+    protected $blockResource;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Cms\Model\Block
+     */
+    protected $block;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Cms\Api\Data\BlockInterface
+     */
+    protected $blockData;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Cms\Api\Data\BlockSearchResultsInterface
+     */
+    protected $blockSearchResult;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Api\DataObjectHelper
+     */
+    protected $dataHelper;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Cms\Model\Resource\Block\Collection
+     */
+    protected $collection;
+
+    /**
+     * Initialize repository
+     */
+    public function setUp()
+    {
+        $this->blockResource = $this->getMockBuilder('Magento\Cms\Model\Resource\Block')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $blockFactory = $this->getMockBuilder('Magento\Cms\Model\BlockFactory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+        $blockDataFactory = $this->getMockBuilder('Magento\Cms\Api\Data\BlockInterfaceFactory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+        $blockSearchResultFactory = $this->getMockBuilder('Magento\Cms\Api\Data\BlockSearchResultsInterfaceFactory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+        $collectionFactory = $this->getMockBuilder('Magento\Cms\Model\Resource\Block\CollectionFactory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+
+        $this->block = $this->getMockBuilder('Magento\Cms\Model\Block')->disableOriginalConstructor()->getMock();
+        $this->blockData = $this->getMockBuilder('Magento\Cms\Api\Data\BlockInterface')
+            ->getMock();
+        $this->blockSearchResult = $this->getMockBuilder('Magento\Cms\Api\Data\BlockSearchResultsInterface')
+            ->getMock();
+        $this->collection = $this->getMockBuilder('Magento\Cms\Model\Resource\Block\Collection')
+            ->disableOriginalConstructor()
+            ->setMethods(['addFieldToFilter', 'getSize', 'setCurPage', 'setPageSize', 'load', 'addOrder'])
+            ->getMock();
+
+        $blockFactory->expects($this->any())
+            ->method('create')
+            ->willReturn($this->block);
+        $blockDataFactory->expects($this->any())
+            ->method('create')
+            ->willReturn($this->blockData);
+        $blockSearchResultFactory->expects($this->any())
+            ->method('create')
+            ->willReturn($this->blockSearchResult);
+        $collectionFactory->expects($this->any())
+            ->method('create')
+            ->willReturn($this->collection);
+        /**
+         * @var \Magento\Cms\Model\BlockFactory $blockFactory
+         * @var \Magento\Cms\Api\Data\BlockInterfaceFactory $blockDataFactory
+         * @var \Magento\Cms\Api\Data\BlockSearchResultsInterfaceFactory $blockSearchResultFactory
+         * @var \Magento\Cms\Model\Resource\Block\CollectionFactory $collectionFactory
+         */
+
+        $this->dataHelper = $this->getMockBuilder('Magento\Framework\Api\DataObjectHelper')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->repository = new BlockRepository(
+            $this->blockResource,
+            $blockFactory,
+            $blockDataFactory,
+            $collectionFactory,
+            $blockSearchResultFactory,
+            $this->dataHelper
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function testSave()
+    {
+        $this->blockResource->expects($this->once())
+            ->method('save')
+            ->with($this->block)
+            ->willReturnSelf();
+        $this->assertEquals($this->block, $this->repository->save($this->block));
+    }
+
+    /**
+     * @test
+     */
+    public function testDeleteById()
+    {
+        $blockId = '123';
+
+        $this->block->expects($this->once())
+            ->method('getId')
+            ->willReturn(true);
+        $this->blockResource->expects($this->once())
+            ->method('load')
+            ->with($this->block, $blockId)
+            ->willReturn($this->block);
+        $this->blockResource->expects($this->once())
+            ->method('delete')
+            ->with($this->block)
+            ->willReturnSelf();
+
+        $this->assertTrue($this->repository->deleteById($blockId));
+    }
+
+    /**
+     * @test
+     *
+     * @expectedException \Magento\Framework\Exception\CouldNotSaveException
+     */
+    public function testSaveException()
+    {
+        $this->blockResource->expects($this->once())
+            ->method('save')
+            ->with($this->block)
+            ->willThrowException(new \Exception());
+        $this->repository->save($this->block);
+    }
+
+    /**
+     * @test
+     *
+     * @expectedException \Magento\Framework\Exception\CouldNotDeleteException
+     */
+    public function testDeleteException()
+    {
+        $this->blockResource->expects($this->once())
+            ->method('delete')
+            ->with($this->block)
+            ->willThrowException(new \Exception());
+        $this->repository->delete($this->block);
+    }
+
+    /**
+     * @test
+     *
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function testGetByIdException()
+    {
+        $blockId = '123';
+
+        $this->block->expects($this->once())
+            ->method('getId')
+            ->willReturn(false);
+        $this->blockResource->expects($this->once())
+            ->method('load')
+            ->with($this->block, $blockId)
+            ->willReturn($this->block);
+        $this->repository->getById($blockId);
+    }
+
+    /**
+     * @test
+     */
+    public function testGetList()
+    {
+        $field = 'name';
+        $value = 'magento';
+        $condition = 'eq';
+        $total = 10;
+        $currentPage = 3;
+        $pageSize = 2;
+        $sortField = 'id';
+
+        $criteria = $this->getMockBuilder('Magento\Framework\Api\SearchCriteriaInterface')->getMock();
+        $filterGroup = $this->getMockBuilder('Magento\Framework\Api\Search\FilterGroup')->getMock();
+        $filter = $this->getMockBuilder('Magento\Framework\Api\Filter')->getMock();
+        $storeFilter = $this->getMockBuilder('Magento\Framework\Api\Filter')->getMock();
+        $sortOrder = $this->getMockBuilder('Magento\Framework\Api\SortOrder')->getMock();
+
+        $criteria->expects($this->once())
+            ->method('getFilterGroups')
+            ->willReturn([$filterGroup]);
+        $criteria->expects($this->once())
+            ->method('getSortOrders')
+            ->willReturn([$sortOrder]);
+        $criteria->expects($this->once())
+            ->method('getCurrentPage')
+            ->willReturn($currentPage);
+        $criteria->expects($this->once())
+            ->method('getPageSize')
+            ->willReturn($pageSize);
+        $filterGroup->expects($this->once())
+            ->method('getFilters')
+            ->willReturn([$storeFilter, $filter]);
+        $filter->expects($this->once())
+            ->method('getConditionType')
+            ->willReturn($condition);
+        $filter->expects($this->any())
+            ->method('getField')
+            ->willReturn($field);
+        $filter->expects($this->once())
+            ->method('getValue')
+            ->willReturn($value);
+        $storeFilter->expects($this->any())
+            ->method('getField')
+            ->willReturn('store_id');
+        $storeFilter->expects($this->once())
+            ->method('getValue')
+            ->willReturn(1);
+        $sortOrder->expects($this->once())
+            ->method('getField')
+            ->willReturn($sortField);
+        $sortOrder->expects($this->once())
+            ->method('getDirection')
+            ->willReturn(SearchCriteriaInterface::SORT_DESC);
+
+        /** @var \Magento\Framework\Api\SearchCriteriaInterface $criteria */
+
+        $this->collection->addItem($this->block);
+        $this->blockSearchResult->expects($this->once())
+            ->method('setSearchCriteria')
+            ->with($criteria)
+            ->willReturnSelf();
+        $this->collection->expects($this->once())
+            ->method('addFieldToFilter')
+            ->with([['attribute' => $field, $condition => $value]], [])
+            ->willReturnSelf();
+        $this->blockSearchResult->expects($this->once())
+            ->method('setTotalCount')
+            ->with($total)
+            ->willReturnSelf();
+        $this->collection->expects($this->once())
+            ->method('getSize')
+            ->willReturn($total);
+        $this->collection->expects($this->once())
+            ->method('setCurPage')
+            ->with($currentPage)
+            ->willReturnSelf();
+        $this->collection->expects($this->once())
+            ->method('setPageSize')
+            ->with($pageSize)
+            ->willReturnSelf();
+        $this->collection->expects($this->once())
+            ->method('addOrder')
+            ->with($sortField, 'DESC')
+            ->willReturnSelf();
+        $this->block->expects($this->once())
+            ->method('getData')
+            ->willReturn(['data']);
+        $this->blockSearchResult->expects($this->once())
+            ->method('setItems')
+            ->with(['someData'])
+            ->willReturnSelf();
+        $this->dataHelper->expects($this->once())
+            ->method('populateWithArray')
+            ->with($this->blockData, ['data'], 'Magento\Cms\Api\Data\BlockInterface')
+            ->willReturn('someData');
+
+        $this->assertEquals($this->blockSearchResult, $this->repository->getList($criteria));
+    }
+}
diff --git a/app/code/Magento/Cms/Test/Unit/Model/Config/Source/PageTest.php b/app/code/Magento/Cms/Test/Unit/Model/Config/Source/PageTest.php
index 234de25b3a6866038240be08d00d6fbc2da77370..a4602ea501dc26e141aa9003b763bd33ac7c745e 100644
--- a/app/code/Magento/Cms/Test/Unit/Model/Config/Source/PageTest.php
+++ b/app/code/Magento/Cms/Test/Unit/Model/Config/Source/PageTest.php
@@ -11,14 +11,9 @@ namespace Magento\Cms\Test\Unit\Model\Config\Source;
 class PageTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Cms\Model\PageRepository|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Cms\Model\Resource\Page\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $pageRepositoryMock;
-
-    /**
-     * @var \Magento\Cms\Model\Resource\PageCriteria|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $pageCriteriaFactoryMock;
+    protected $collectionFactory;
 
     /**
      * @var \Magento\Cms\Model\Config\Source\Page
@@ -34,15 +29,8 @@ class PageTest extends \PHPUnit_Framework_TestCase
     {
         $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
 
-        $this->pageRepositoryMock = $this->getMock(
-            'Magento\Cms\Model\PageRepository',
-            [],
-            [],
-            '',
-            false
-        );
-        $this->pageCriteriaFactoryMock = $this->getMock(
-            'Magento\Cms\Model\Resource\PageCriteriaFactory',
+        $this->collectionFactory = $this->getMock(
+            'Magento\Cms\Model\Resource\Page\CollectionFactory',
             ['create'],
             [],
             '',
@@ -52,8 +40,7 @@ class PageTest extends \PHPUnit_Framework_TestCase
         $this->page = $objectManager->getObject(
             'Magento\Cms\Model\Config\Source\Page',
             [
-                'pageRepository' => $this->pageRepositoryMock,
-                'pageCriteriaFactory' => $this->pageCriteriaFactoryMock
+                'collectionFactory' => $this->collectionFactory,
             ]
         );
     }
@@ -72,22 +59,10 @@ class PageTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $pageCriteriaMock = $this->getMock(
-            'Magento\Cms\Model\Resource\PageCriteria',
-            [],
-            [],
-            '',
-            false
-        );
-
-        $this->pageRepositoryMock->expects($this->once())
-            ->method('getList')
-            ->with($pageCriteriaMock)
-            ->will($this->returnValue($pageCollectionMock));
 
-        $this->pageCriteriaFactoryMock->expects($this->once())
+        $this->collectionFactory->expects($this->once())
             ->method('create')
-            ->will($this->returnValue($pageCriteriaMock));
+            ->will($this->returnValue($pageCollectionMock));
 
         $pageCollectionMock->expects($this->once())
             ->method('toOptionIdArray')
diff --git a/app/code/Magento/Cms/Test/Unit/Model/DataSource/PageCollectionTest.php b/app/code/Magento/Cms/Test/Unit/Model/DataSource/PageCollectionTest.php
deleted file mode 100644
index 227a7c2280ccc75e1b0a457fb5f2119b0794072b..0000000000000000000000000000000000000000
--- a/app/code/Magento/Cms/Test/Unit/Model/DataSource/PageCollectionTest.php
+++ /dev/null
@@ -1,106 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Cms\Test\Unit\Model\DataSource;
-
-/**
- * Class PageCollectionTest
- */
-class PageCollectionTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * @var \Magento\Cms\Model\Resource\PageCriteria|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $criteriaMock;
-
-    /**
-     * @var \Magento\Cms\Model\PageRepository|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $repositoryMock;
-
-    /**
-     * @var \Magento\Cms\Model\DataSource\PageCollection
-     */
-    protected $pageCollection;
-
-    /**
-     * Set up
-     *
-     * @return void
-     */
-    protected function setUp()
-    {
-        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
-        $this->repositoryMock = $this->getMock(
-            'Magento\Cms\Model\PageRepository',
-            [],
-            [],
-            '',
-            false
-        );
-
-        $this->pageCollection = $objectManager->getObject(
-            'Magento\Cms\Model\DataSource\PageCollection',
-            [
-                'repository' => $this->repositoryMock,
-                'mapper' => ''
-            ]
-        );
-    }
-
-    /**
-     * Run test addFilter method
-     *
-     * @param string $name
-     * @param string $field
-     * @param mixed $condition
-     * @param string $type
-     * @return void
-     *
-     * @dataProvider dataProviderAddFilter
-     */
-    public function testAddFilter($name, $field, $condition, $type)
-    {
-        $this->pageCollection->addFilter($name, $field, $condition, $type);
-    }
-
-    /**
-     * Run test getResultCollection method
-     *
-     * @return void
-     */
-    public function testGetResultCollection()
-    {
-        $this->repositoryMock->expects($this->once())
-            ->method('getList')
-            ->with($this->pageCollection)
-            ->will($this->returnValue('return-value'));
-
-        $this->assertEquals('return-value', $this->pageCollection->getResultCollection());
-    }
-
-    /**
-     * Data provider for addFilter method
-     *
-     * @return array
-     */
-    public function dataProviderAddFilter()
-    {
-        return [
-            [
-                'name' => 'test-name',
-                'field' => 'store_id',
-                'condition' => null,
-                'type' => 'public',
-            ],
-            [
-                'name' => 'test-name',
-                'field' => 'any_field',
-                'condition' => 10,
-                'type' => 'private'
-            ]
-        ];
-    }
-}
diff --git a/app/code/Magento/Cms/Test/Unit/Model/PageRepositoryTest.php b/app/code/Magento/Cms/Test/Unit/Model/PageRepositoryTest.php
index d300268f7ab044c6228031707df86c8dd1d29f43..a5127dc51823910b45ebcc68d6c1cca26e53541a 100644
--- a/app/code/Magento/Cms/Test/Unit/Model/PageRepositoryTest.php
+++ b/app/code/Magento/Cms/Test/Unit/Model/PageRepositoryTest.php
@@ -5,261 +5,296 @@
  */
 namespace Magento\Cms\Test\Unit\Model;
 
+use Magento\Cms\Model\PageRepository;
+use Magento\Framework\Api\SearchCriteriaInterface;
+
 /**
- * Class PageRepositoryTest
+ * Test for Magento\Cms\Model\PageRepository
  */
 class PageRepositoryTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Cms\Model\Resource\Page|\PHPUnit_Framework_MockObject_MockObject
+     * @var PageRepository
      */
-    protected $resourceMock;
+    protected $repository;
 
     /**
-     * @var \Magento\Cms\Model\PageFactory|\PHPUnit_Framework_MockObject_MockObject
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Cms\Model\Resource\Page
      */
-    protected $pageFactoryMock;
+    protected $pageResource;
 
     /**
-     * @var \Magento\Cms\Model\Resource\Page\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Cms\Model\Page
      */
-    protected $pageCollectionFactoryMock;
+    protected $page;
 
     /**
-     * @var \Magento\Framework\DB\QueryBuilderFactory|\PHPUnit_Framework_MockObject_MockObject
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Cms\Api\Data\PageInterface
      */
-    protected $queryBuilderFactoryMock;
+    protected $pageData;
 
     /**
-     * @var \Magento\Framework\DB\MapperFactory|\PHPUnit_Framework_MockObject_MockObject
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Cms\Api\Data\PageSearchResultsInterface
      */
-    protected $mapperFactoryMock;
+    protected $pageSearchResult;
 
     /**
-     * @var \Magento\Cms\Model\PageRepository
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Api\DataObjectHelper
      */
-    protected $pageRepository;
+    protected $dataHelper;
 
     /**
-     * Set up
-     *
-     * @return void
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Cms\Model\Resource\Page\Collection
      */
-    protected function setUp()
+    protected $collection;
+
+    /**
+     * Initialize repository
+     */
+    public function setUp()
     {
-        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+        $this->pageResource = $this->getMockBuilder('Magento\Cms\Model\Resource\Page')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $pageFactory = $this->getMockBuilder('Magento\Cms\Model\PageFactory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+        $pageDataFactory = $this->getMockBuilder('Magento\Cms\Api\Data\PageInterfaceFactory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+        $pageSearchResultFactory = $this->getMockBuilder('Magento\Cms\Api\Data\PageSearchResultsInterfaceFactory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+        $collectionFactory = $this->getMockBuilder('Magento\Cms\Model\Resource\Page\CollectionFactory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
 
-        $this->resourceMock = $this->getMock(
-            'Magento\Cms\Model\Resource\Page',
-            ['save', 'load', 'delete'],
-            [],
-            '',
-            false
-        );
-        $this->pageFactoryMock = $this->getMock(
-            'Magento\Cms\Model\PageFactory',
-            ['create'],
-            [],
-            '',
-            false
-        );
-        $this->pageCollectionFactoryMock = $this->getMock(
-            'Magento\Cms\Model\Resource\Page\CollectionFactory',
-            ['create'],
-            [],
-            '',
-            false
-        );
-        $this->queryBuilderFactoryMock = $this->getMock(
-            'Magento\Framework\DB\QueryBuilderFactory',
-            ['create'],
-            [],
-            '',
-            false
-        );
-        $this->mapperFactoryMock = $this->getMock(
-            'Magento\Framework\DB\MapperFactory',
-            [],
-            [],
-            '',
-            false
-        );
+        $this->page = $this->getMockBuilder('Magento\Cms\Model\Page')->disableOriginalConstructor()->getMock();
+        $this->pageData = $this->getMockBuilder('Magento\Cms\Api\Data\PageInterface')
+            ->getMock();
+        $this->pageSearchResult = $this->getMockBuilder('Magento\Cms\Api\Data\PageSearchResultsInterface')
+            ->getMock();
+        $this->collection = $this->getMockBuilder('Magento\Cms\Model\Resource\Page\Collection')
+            ->disableOriginalConstructor()
+            ->setMethods(['addFieldToFilter', 'getSize', 'setCurPage', 'setPageSize', 'load', 'addOrder'])
+            ->getMock();
+
+        $pageFactory->expects($this->any())
+            ->method('create')
+            ->willReturn($this->page);
+        $pageDataFactory->expects($this->any())
+            ->method('create')
+            ->willReturn($this->pageData);
+        $pageSearchResultFactory->expects($this->any())
+            ->method('create')
+            ->willReturn($this->pageSearchResult);
+        $collectionFactory->expects($this->any())
+            ->method('create')
+            ->willReturn($this->collection);
+        /**
+         * @var \Magento\Cms\Model\PageFactory $pageFactory
+         * @var \Magento\Cms\Api\Data\PageInterfaceFactory $pageDataFactory
+         * @var \Magento\Cms\Api\Data\PageSearchResultsInterfaceFactory $pageSearchResultFactory
+         * @var \Magento\Cms\Model\Resource\Page\CollectionFactory $collectionFactory
+         */
+
+        $this->dataHelper = $this->getMockBuilder('Magento\Framework\Api\DataObjectHelper')
+            ->disableOriginalConstructor()
+            ->getMock();
 
-        $this->pageRepository = $objectManager->getObject(
-            'Magento\Cms\Model\PageRepository',
-            [
-                'resource' => $this->resourceMock,
-                'pageFactory' => $this->pageFactoryMock,
-                'pageCollectionFactory' => $this->pageCollectionFactoryMock,
-                'queryBuilderFactory' => $this->queryBuilderFactoryMock,
-                'mapperFactory' => $this->mapperFactoryMock
-            ]
+        $this->repository = new PageRepository(
+            $this->pageResource,
+            $pageFactory,
+            $pageDataFactory,
+            $collectionFactory,
+            $pageSearchResultFactory,
+            $this->dataHelper
         );
     }
 
     /**
-     * Run test save method
-     *
-     * @return void
+     * @test
      */
     public function testSave()
     {
-        $pageMock = $this->getMock(
-            'Magento\Cms\Model\Page',
-            [],
-            [],
-            '',
-            false
-        );
-
-        $this->resourceMock->expects($this->once())
+        $this->pageResource->expects($this->once())
             ->method('save')
-            ->with($pageMock);
-
-        $this->assertEquals($pageMock, $this->pageRepository->save($pageMock));
+            ->with($this->page)
+            ->willReturnSelf();
+        $this->assertEquals($this->page, $this->repository->save($this->page));
     }
 
     /**
-     * Run test get method
-     *
-     * @return void
+     * @test
      */
-    public function testGet()
+    public function testDeleteById()
     {
-        $id = 20;
-        $pageMock = $this->getMockForAbstractClass(
-            'Magento\Cms\Model\Page',
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['getId']
-        );
+        $pageId = '123';
 
-        $pageMock->expects($this->atLeastOnce())
+        $this->page->expects($this->once())
             ->method('getId')
-            ->will($this->returnValue($id));
-        $this->pageFactoryMock->expects($this->once())
-            ->method('create')
-            ->will($this->returnValue($pageMock));
-        $this->resourceMock->expects($this->once())
+            ->willReturn(true);
+        $this->pageResource->expects($this->once())
             ->method('load')
-            ->with($pageMock, $id);
+            ->with($this->page, $pageId)
+            ->willReturn($this->page);
+        $this->pageResource->expects($this->once())
+            ->method('delete')
+            ->with($this->page)
+            ->willReturnSelf();
 
-        $this->assertEquals($pageMock, $this->pageRepository->get($id));
+        $this->assertTrue($this->repository->deleteById($pageId));
     }
 
     /**
-     * Run test getList method
+     * @test
      *
-     * @return void
+     * @expectedException \Magento\Framework\Exception\CouldNotSaveException
      */
-    public function testGetList()
+    public function testSaveException()
     {
-        $criteriaMock = $this->getMock(
-            'Magento\Cms\Model\Resource\PageCriteria',
-            [],
-            [],
-            '',
-            false
-        );
-        $queryBuilderMock = $this->getMock(
-            'Magento\Framework\DB\QueryBuilder',
-            ['setCriteria', 'setResource', 'create'],
-            [],
-            '',
-            false
-        );
-        $queryMock = $this->getMockForAbstractClass(
-            'Magento\Framework\DB\QueryInterface',
-            [],
-            '',
-            false
-        );
-        $collectionMock = $this->getMock(
-            'Magento\Cms\Model\Resource\Page\Collection',
-            [],
-            [],
-            '',
-            false
-        );
-
-        $this->queryBuilderFactoryMock->expects($this->once())
-            ->method('create')
-            ->will($this->returnValue($queryBuilderMock));
-        $queryBuilderMock->expects($this->once())
-            ->method('setCriteria')
-            ->with($criteriaMock);
-        $queryBuilderMock->expects($this->once())
-            ->method('setResource')
-            ->with($this->resourceMock);
-        $queryBuilderMock->expects($this->once())
-            ->method('create')
-            ->will($this->returnValue($queryMock));
-        $this->pageCollectionFactoryMock->expects($this->once())
-            ->method('create')
-            ->with(['query' => $queryMock])
-            ->will($this->returnValue($collectionMock));
-
-        $this->assertEquals($collectionMock, $this->pageRepository->getList($criteriaMock));
+        $this->pageResource->expects($this->once())
+            ->method('save')
+            ->with($this->page)
+            ->willThrowException(new \Exception());
+        $this->repository->save($this->page);
     }
 
     /**
-     * Run test delete method
+     * @test
      *
-     * @return void
+     * @expectedException \Magento\Framework\Exception\CouldNotDeleteException
      */
-    public function testDelete()
+    public function testDeleteException()
     {
-        $pageMock = $this->getMockForAbstractClass(
-            'Magento\Cms\Model\Page',
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['getPageId']
-        );
-
-        $this->resourceMock->expects($this->once())
+        $this->pageResource->expects($this->once())
             ->method('delete')
-            ->with($pageMock);
-
-        $this->assertTrue($this->pageRepository->delete($pageMock));
+            ->with($this->page)
+            ->willThrowException(new \Exception());
+        $this->repository->delete($this->page);
     }
 
     /**
-     * Run test deleteById method
+     * @test
      *
-     * @return void
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
      */
-    public function testDeleteById()
+    public function testGetByIdException()
     {
-        $id = 20;
-        $pageMock = $this->getMockForAbstractClass(
-            'Magento\Cms\Model\Page',
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['getId']
-        );
+        $pageId = '123';
 
-        $this->pageFactoryMock->expects($this->once())
-            ->method('create')
-            ->will($this->returnValue($pageMock));
-        $this->resourceMock->expects($this->once())
-            ->method('load')
-            ->with($pageMock, $id);
-        $pageMock->expects($this->once())
+        $this->page->expects($this->once())
             ->method('getId')
-            ->will($this->returnValue($id));
-        $this->resourceMock->expects($this->once())
-            ->method('delete')
-            ->with($pageMock);
+            ->willReturn(false);
+        $this->pageResource->expects($this->once())
+            ->method('load')
+            ->with($this->page, $pageId)
+            ->willReturn($this->page);
+        $this->repository->getById($pageId);
+    }
+
+    /**
+     * @test
+     */
+    public function testGetList()
+    {
+        $field = 'name';
+        $value = 'magento';
+        $condition = 'eq';
+        $total = 10;
+        $currentPage = 3;
+        $pageSize = 2;
+        $sortField = 'id';
+
+        $criteria = $this->getMockBuilder('Magento\Framework\Api\SearchCriteriaInterface')->getMock();
+        $filterGroup = $this->getMockBuilder('Magento\Framework\Api\Search\FilterGroup')->getMock();
+        $filter = $this->getMockBuilder('Magento\Framework\Api\Filter')->getMock();
+        $storeFilter = $this->getMockBuilder('Magento\Framework\Api\Filter')->getMock();
+        $sortOrder = $this->getMockBuilder('Magento\Framework\Api\SortOrder')->getMock();
+
+        $criteria->expects($this->once())
+            ->method('getFilterGroups')
+            ->willReturn([$filterGroup]);
+        $criteria->expects($this->once())
+            ->method('getSortOrders')
+            ->willReturn([$sortOrder]);
+        $criteria->expects($this->once())
+            ->method('getCurrentPage')
+            ->willReturn($currentPage);
+        $criteria->expects($this->once())
+            ->method('getPageSize')
+            ->willReturn($pageSize);
+        $filterGroup->expects($this->once())
+            ->method('getFilters')
+            ->willReturn([$storeFilter, $filter]);
+        $filter->expects($this->once())
+            ->method('getConditionType')
+            ->willReturn($condition);
+        $filter->expects($this->any())
+            ->method('getField')
+            ->willReturn($field);
+        $filter->expects($this->once())
+            ->method('getValue')
+            ->willReturn($value);
+        $storeFilter->expects($this->any())
+            ->method('getField')
+            ->willReturn('store_id');
+        $storeFilter->expects($this->once())
+            ->method('getValue')
+            ->willReturn(1);
+        $sortOrder->expects($this->once())
+            ->method('getField')
+            ->willReturn($sortField);
+        $sortOrder->expects($this->once())
+            ->method('getDirection')
+            ->willReturn(SearchCriteriaInterface::SORT_DESC);
+
+        /** @var \Magento\Framework\Api\SearchCriteriaInterface $criteria */
+
+        $this->collection->addItem($this->page);
+        $this->pageSearchResult->expects($this->once())
+            ->method('setSearchCriteria')
+            ->with($criteria)
+            ->willReturnSelf();
+        $this->collection->expects($this->once())
+            ->method('addFieldToFilter')
+            ->with([['attribute' => $field, $condition => $value]], [])
+            ->willReturnSelf();
+        $this->pageSearchResult->expects($this->once())
+            ->method('setTotalCount')
+            ->with($total)
+            ->willReturnSelf();
+        $this->collection->expects($this->once())
+            ->method('getSize')
+            ->willReturn($total);
+        $this->collection->expects($this->once())
+            ->method('setCurPage')
+            ->with($currentPage)
+            ->willReturnSelf();
+        $this->collection->expects($this->once())
+            ->method('setPageSize')
+            ->with($pageSize)
+            ->willReturnSelf();
+        $this->collection->expects($this->once())
+            ->method('addOrder')
+            ->with($sortField, 'DESC')
+            ->willReturnSelf();
+        $this->page->expects($this->once())
+            ->method('getData')
+            ->willReturn(['data']);
+        $this->pageSearchResult->expects($this->once())
+            ->method('setItems')
+            ->with(['someData'])
+            ->willReturnSelf();
+        $this->dataHelper->expects($this->once())
+            ->method('populateWithArray')
+            ->with($this->pageData, ['data'], 'Magento\Cms\Api\Data\PageInterface')
+            ->willReturn('someData');
 
-        $this->assertTrue($this->pageRepository->deleteById($id));
+        $this->assertEquals($this->pageSearchResult, $this->repository->getList($criteria));
     }
 }
diff --git a/app/code/Magento/Cms/Test/Unit/Model/Resource/Block/Grid/CollectionTest.php b/app/code/Magento/Cms/Test/Unit/Model/Resource/Block/Grid/CollectionTest.php
index 9db74457f743fa561510a622b3c439472a819085..5b267bc224b84db9894c9416ecc26deac3f8fb4c 100644
--- a/app/code/Magento/Cms/Test/Unit/Model/Resource/Block/Grid/CollectionTest.php
+++ b/app/code/Magento/Cms/Test/Unit/Model/Resource/Block/Grid/CollectionTest.php
@@ -5,7 +5,7 @@
  */
 namespace Magento\Cms\Test\Unit\Model\Resource\Block\Grid;
 
-use Magento\Cms\Model\Resource\Block\Grid\Collection;
+use Magento\Cms\Model\Resource\Block\Collection;
 
 class CollectionTest extends \PHPUnit_Framework_TestCase
 {
@@ -42,11 +42,11 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
 
         $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
         $arguments = $objectManagerHelper->getConstructArguments(
-            'Magento\Cms\Model\Resource\Block\Grid\Collection',
+            'Magento\Cms\Model\Resource\Block\Collection',
             ['resource' => $resource, 'connection' => $connection]
         );
 
-        $this->collection = $this->getMockBuilder('Magento\Cms\Model\Resource\Block\Grid\Collection')
+        $this->collection = $this->getMockBuilder('Magento\Cms\Model\Resource\Block\Collection')
             ->setConstructorArgs($arguments)
             ->setMethods(['addFilter', '_translateCondition', 'getMainTable'])
             ->getMock();
diff --git a/app/code/Magento/Cms/Test/Unit/Model/Resource/Page/CollectionTest.php b/app/code/Magento/Cms/Test/Unit/Model/Resource/Page/CollectionTest.php
deleted file mode 100644
index 2abd96842cf321873d5d6949bcf80f4d1e954d30..0000000000000000000000000000000000000000
--- a/app/code/Magento/Cms/Test/Unit/Model/Resource/Page/CollectionTest.php
+++ /dev/null
@@ -1,278 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Cms\Test\Unit\Model\Resource\Page;
-
-/**
- * Class CollectionTest
- */
-class CollectionTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $storeManagerMock;
-
-    /**
-     * @var \Magento\Framework\DB\QueryInterface|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $queryMock;
-
-    /**
-     * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $eventManagerMock;
-
-    /**
-     * @var \Magento\Framework\Data\Collection\EntityFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $entityFactoryMock;
-
-    /**
-     * @var \Magento\Framework\Data\SearchResultIteratorFactory|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $resultIteratorFactoryMock;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $searchResultProcessorMock;
-
-    /**
-     * @var \Magento\Cms\Model\Resource\Page\Collection
-     */
-    protected $collection;
-
-    /**
-     * Set up
-     *
-     * @return void
-     */
-    protected function setUp()
-    {
-        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
-
-        $this->queryMock = $this->getMockForAbstractClass(
-            'Magento\Framework\DB\QueryInterface',
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['fetchAll', 'getIdFieldName', 'getConnection', 'getResource']
-        );
-        $this->entityFactoryMock = $this->getMockForAbstractClass(
-            'Magento\Framework\Data\Collection\EntityFactoryInterface',
-            [],
-            '',
-            false,
-            true,
-            true,
-            []
-        );
-        $this->eventManagerMock = $this->getMockForAbstractClass(
-            'Magento\Framework\Event\ManagerInterface',
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['dispatch']
-        );
-        $this->resultIteratorFactoryMock = $this->getMock(
-            'Magento\Framework\Data\SearchResultIteratorFactory',
-            [],
-            [],
-            '',
-            false
-        );
-        $this->searchResultProcessorMock = $this->getMock(
-            'Magento\Framework\Data\SearchResultProcessor',
-            [],
-            [],
-            '',
-            false
-        );
-        $searchResultProcessorFactoryMock = $this->getMock(
-            'Magento\Framework\Data\SearchResultProcessorFactory',
-            [],
-            [],
-            '',
-            false
-        );
-        $searchResultProcessorFactoryMock->expects($this->any())
-            ->method('create')
-            ->withAnyParameters()
-            ->willReturn($this->searchResultProcessorMock);
-        $this->storeManagerMock = $this->getMockForAbstractClass(
-            'Magento\Store\Model\StoreManagerInterface',
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['getStore']
-        );
-
-        $this->collection = $objectManager->getObject(
-            'Magento\Cms\Model\Resource\Page\Collection',
-            [
-                'query' => $this->queryMock,
-                'entityFactory' => $this->entityFactoryMock,
-                'eventManager' => $this->eventManagerMock,
-                'resultIteratorFactory' => $this->resultIteratorFactoryMock,
-                'storeManager' => $this->storeManagerMock,
-                'searchResultProcessorFactory' => $searchResultProcessorFactoryMock
-            ]
-        );
-    }
-
-    /**
-     * Run test toOptionIdArray method
-     *
-     * @return void
-     *
-     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
-     */
-    public function testToOptionIdArray()
-    {
-        $itemsByPageId = array_fill(0, 4, 123);
-        $data = [
-            'item1' => ['test' => 'test'],
-            'item2' => ['test' => 'test'],
-            'item3' => ['test' => 'test'],
-            'item4' => ['test' => 'test'],
-        ];
-
-        $objectMock = $this->getMock(
-            'Magento\Framework\Object',
-            ['getData', 'getId', 'setData', 'getTitle', 'getIdentifier'],
-            [],
-            '',
-            false
-        );
-        $criteriaMock = $this->getMockForAbstractClass('Magento\Framework\Api\CriteriaInterface');
-        $connectionMock = $this->getMockForAbstractClass('Magento\Framework\DB\Adapter\AdapterInterface');
-        $resourceMock = $this->getMockForAbstractClass(
-            'Magento\Framework\Model\Resource\Db\AbstractDb',
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['getTable']
-        );
-        $selectMock = $this->getMock(
-            'Magento\Framework\DB\Select',
-            ['from', 'where'],
-            [],
-            '',
-            false
-        );
-        $storeMock = $this->getMock(
-            'Magento\Store\Model\Store',
-            ['getCode'],
-            [],
-            '',
-            false
-        );
-
-        $this->queryMock->expects($this->once())
-            ->method('fetchAll')
-            ->will($this->returnValue($data));
-
-        $this->searchResultProcessorMock->expects($this->once())
-            ->method('getColumnValues')
-            ->with('page_id')
-            ->will($this->returnValue($itemsByPageId));
-        $this->queryMock->expects($this->any())
-            ->method('getIdFieldName')
-            ->will($this->returnValue('id_field_name'));
-        $objectMock->expects($this->any())
-            ->method('getData')
-            ->will(
-                $this->returnValueMap(
-                    [
-                        ['id_field_name', null, null],
-                        ['page_id', null, 123],
-                    ]
-                )
-            );
-        $this->entityFactoryMock->expects($this->any())
-            ->method('create')
-            ->with('Magento\Cms\Model\Page', ['data' => ['test' => 'test']])
-            ->will($this->returnValue($objectMock));
-        $this->queryMock->expects($this->once())
-            ->method('getCriteria')
-            ->will($this->returnValue($criteriaMock));
-        $criteriaMock->expects($this->once())
-            ->method('getPart')
-            ->with('first_store_flag')
-            ->will($this->returnValue(true));
-        $this->queryMock->expects($this->once())
-            ->method('getConnection')
-            ->will($this->returnValue($connectionMock));
-        $this->queryMock->expects($this->once())
-            ->method('getResource')
-            ->will($this->returnValue($resourceMock));
-        $connectionMock->expects($this->once())
-            ->method('select')
-            ->will($this->returnValue($selectMock));
-        $selectMock->expects($this->once())
-            ->method('from')
-            ->with(['cps' => 'query_table'])
-            ->will($this->returnSelf());
-        $resourceMock->expects($this->once())
-            ->method('getTable')
-            ->with('cms_page_store')
-            ->will($this->returnValue('query_table'));
-        $selectMock->expects($this->once())
-            ->method('where')
-            ->with('cps.page_id IN (?)', array_fill(0, 4, 123))
-            ->will($this->returnSelf());
-        $connectionMock->expects($this->once())
-            ->method('fetchPairs')
-            ->with($selectMock)
-            ->will($this->returnValue([123 => 999]));
-        $objectMock->expects($this->any())
-            ->method('getId')
-            ->will($this->returnValue(123));
-        $this->storeManagerMock->expects($this->any())
-            ->method('getStore')
-            ->with(999)
-            ->will($this->returnValue($storeMock));
-        $storeMock->expects($this->any())
-            ->method('getCode')
-            ->will($this->returnValue('store_code'));
-        $objectMock->expects($this->any())
-            ->method('setData');
-        $objectMock->expects($this->any())
-            ->method('getTitle')
-            ->will($this->returnValue('item-value'));
-        $objectMock->expects($this->any())
-            ->method('getIdentifier')
-            ->will($this->returnValue('identifier-value'));
-
-        $expected = [
-            [
-                'value' => 'identifier-value',
-                'label' => 'item-value',
-            ],
-            [
-                'value' => 'identifier-value|123',
-                'label' => 'item-value'
-            ],
-            [
-                'value' => 'identifier-value|123',
-                'label' => 'item-value'
-            ],
-            [
-                'value' => 'identifier-value|123',
-                'label' => 'item-value'
-            ],
-        ];
-        $this->assertEquals($expected, $this->collection->toOptionIdArray());
-    }
-}
diff --git a/app/code/Magento/Cms/Test/Unit/Model/Resource/PageCriteriaMapperTest.php b/app/code/Magento/Cms/Test/Unit/Model/Resource/PageCriteriaMapperTest.php
deleted file mode 100644
index 19ac623ed6b10f98e592e6308409c401ea961cda..0000000000000000000000000000000000000000
--- a/app/code/Magento/Cms/Test/Unit/Model/Resource/PageCriteriaMapperTest.php
+++ /dev/null
@@ -1,135 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\Cms\Test\Unit\Model\Resource;
-
-/**
- * Class PageCriteriaMapperTest
- */
-class PageCriteriaMapperTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $loggerMock;
-
-    /**
-     * @var \Magento\Framework\Data\Collection\Db\FetchStrategyInterface|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $fetchStrategyMock;
-
-    /**
-     * @var \Magento\Framework\Data\ObjectFactory|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $objectFactoryMock;
-
-    /**
-     * @var \Magento\Framework\DB\MapperFactory|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $mapperFactoryMock;
-
-    /**
-     * @var \Magento\Framework\DB\Select|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $selectMock;
-
-    /**
-     * @var \Magento\Cms\Model\Resource\PageCriteriaMapper|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $pageCriteria;
-
-    /**
-     * Set up
-     *
-     * @return void
-     */
-    protected function setUp()
-    {
-        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
-        $this->fetchStrategyMock = $this->getMockForAbstractClass(
-            'Magento\Framework\Data\Collection\Db\FetchStrategyInterface',
-            [],
-            '',
-            false
-        );
-        $this->objectFactoryMock = $this->getMock(
-            'Magento\Framework\Data\ObjectFactory',
-            [],
-            [],
-            '',
-            false
-        );
-        $this->mapperFactoryMock = $this->getMock(
-            'Magento\Framework\DB\MapperFactory',
-            [],
-            [],
-            '',
-            false
-        );
-        $this->selectMock = $this->getMock(
-            'Magento\Framework\DB\Select',
-            ['join', 'group', 'where'],
-            [],
-            '',
-            false
-        );
-
-        $this->pageCriteria = $this->getMockBuilder('Magento\Cms\Model\Resource\PageCriteriaMapper')
-            ->setConstructorArgs(
-                [
-                    'logger' => $this->loggerMock,
-                    'fetchStrategy' => $this->fetchStrategyMock,
-                    'objectFactory' => $this->objectFactoryMock,
-                    'mapperFactory' => $this->mapperFactoryMock,
-                    'select' => $this->selectMock,
-                ]
-            )->setMethods(['init', 'getTable', 'getMappedField', 'getConditionSql'])
-            ->getMock();
-    }
-
-    /**
-     * Run test mapStoreFilter method
-     *
-     * @return void
-     */
-    public function testMapStoreFilter()
-    {
-        $reflection = new \ReflectionClass($this->pageCriteria);
-        $reflectionProperty = $reflection->getProperty('storeTableName');
-        $reflectionProperty->setAccessible(true);
-        $reflectionProperty->setValue($this->pageCriteria, 'cms_page_store');
-        $reflectionProperty = $reflection->getProperty('linkFieldName');
-        $reflectionProperty->setAccessible(true);
-        $reflectionProperty->setValue($this->pageCriteria, 'page_id');
-
-        $this->pageCriteria->expects($this->once())
-            ->method('getTable')
-            ->with('cms_page_store')
-            ->will($this->returnValue('table-name'));
-        $this->pageCriteria->expects($this->once())
-            ->method('getMappedField')
-            ->with('store')
-            ->will($this->returnValue('mapped-field-result'));
-        $this->selectMock->expects($this->once())
-            ->method('join')
-            ->with(
-                ['store_table' => 'table-name'],
-                'main_table.page_id = store_table.page_id',
-                []
-            )->will($this->returnSelf());
-        $this->selectMock->expects($this->once())
-            ->method('group')
-            ->with('main_table.page_id');
-        $this->pageCriteria->expects($this->once())
-            ->method('getConditionSql')
-            ->with('mapped-field-result', ['in' => [1]])
-            ->will($this->returnValue('condition-sql-result'));
-        $this->selectMock->expects($this->once())
-            ->method('where')
-            ->with('condition-sql-result', null, \Magento\Framework\DB\Select::TYPE_CONDITION);
-
-        $this->pageCriteria->mapStoreFilter(1, false);
-    }
-}
diff --git a/app/code/Magento/Cms/etc/di.xml b/app/code/Magento/Cms/etc/di.xml
index 5180d2671ad2e15dab12a891e221812f0665ab74..d25ddfd399e02b299b8cc9be0c901fe03b795f3d 100644
--- a/app/code/Magento/Cms/etc/di.xml
+++ b/app/code/Magento/Cms/etc/di.xml
@@ -6,8 +6,14 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
-    <preference for="Magento\Cms\Model\PageCriteriaInterface" type="Magento\Cms\Model\Resource\PageCriteria" />
-    <preference for="Magento\Cms\Model\BlockCriteriaInterface" type="Magento\Cms\Model\Resource\BlockCriteria" />
+    <preference for="Magento\Cms\Api\Data\PageSearchResultsInterface"
+                type="Magento\Framework\Api\SearchResults" />
+    <preference for="Magento\Cms\Api\Data\BlockSearchResultsInterface"
+                type="Magento\Framework\Api\SearchResults" />
+    <preference for="Magento\Cms\Api\Data\PageInterface" type="Magento\Cms\Model\Page" />
+    <preference for="Magento\Cms\Api\Data\BlockInterface" type="Magento\Cms\Model\Block" />
+    <preference for="Magento\Cms\Api\BlockRepositoryInterface" type="Magento\Cms\Model\BlockRepository" />
+    <preference for="Magento\Cms\Api\PageRepositoryInterface" type="Magento\Cms\Model\PageRepository" />
     <type name="Magento\Cms\Model\Wysiwyg\Config">
         <arguments>
             <argument name="windowSize" xsi:type="array">
diff --git a/app/code/Magento/Cms/view/adminhtml/layout/cms_block_listing.xml b/app/code/Magento/Cms/view/adminhtml/layout/cms_block_listing.xml
index 83f7ab821f23355be1d399dc85244287af31d8bc..6f1975adb97cd11e5032ed1b455183ac0a653f31 100644
--- a/app/code/Magento/Cms/view/adminhtml/layout/cms_block_listing.xml
+++ b/app/code/Magento/Cms/view/adminhtml/layout/cms_block_listing.xml
@@ -10,7 +10,7 @@
         <referenceBlock name="listing">
             <arguments>
                 <argument name="name" xsi:type="string">cms_block_listing</argument>
-                <argument name="dataSource" xsi:type="object">Magento\Cms\Model\DataSource\BlockCollection</argument>
+                <argument name="dataSource" xsi:type="object">Magento\Cms\Model\Resource\Block\Collection</argument>
                 <argument name="save_parameters_in_session" xsi:type="string">1</argument>
                 <argument name="configuration" xsi:type="array">
                     <item name="page_actions" xsi:type="array">
diff --git a/app/code/Magento/Cms/view/adminhtml/layout/cms_page_listing.xml b/app/code/Magento/Cms/view/adminhtml/layout/cms_page_listing.xml
index 48bdecdc6696955d394dc16dc148d4f231b01c6b..bebf23cacd86b98d4f7e4f6c3af734c4cba77515 100644
--- a/app/code/Magento/Cms/view/adminhtml/layout/cms_page_listing.xml
+++ b/app/code/Magento/Cms/view/adminhtml/layout/cms_page_listing.xml
@@ -10,7 +10,7 @@
         <referenceBlock name="listing">
             <arguments>
                 <argument name="name" xsi:type="string">cms_page_listing</argument>
-                <argument name="dataSource" xsi:type="object">Magento\Cms\Model\DataSource\PageCollection</argument>
+                <argument name="dataSource" xsi:type="object">Magento\Cms\Model\Resource\Page\Collection</argument>
                 <argument name="save_parameters_in_session" xsi:type="string">1</argument>
                 <argument name="configuration" xsi:type="array">
                     <item name="page_actions" xsi:type="array">
diff --git a/app/code/Magento/PageCache/etc/varnish3.vcl b/app/code/Magento/PageCache/etc/varnish3.vcl
index 7fa9a30ec9ac5acdce849c445abfd8efa8cf496f..0b6651fbc0cd4d66748e7d68b683dc823ff574d2 100644
--- a/app/code/Magento/PageCache/etc/varnish3.vcl
+++ b/app/code/Magento/PageCache/etc/varnish3.vcl
@@ -54,7 +54,7 @@ sub vcl_recv {
     std.collect(req.http.Cookie);
 
     # static files are always cacheable. remove SSL flag and cookie
-    if (req.url ~ "^/(pub/)?(media|static)/.*\.(png|jpg|jpeg|gif|css|js|swf|ico|woff|svg)$") {
+    if (req.url ~ "^/(pub/)?(media|static)/.*\.(ico|css|js|jpg|jpeg|png|gif|tiff|bmp|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|woff|woff2|eot|ttf|otf)$") {
         unset req.http.Https;
         unset req.http.Cookie;
     }
@@ -96,7 +96,7 @@ sub vcl_fetch {
     # images, css and js are cacheable by default so we have to remove cookie also
     if (beresp.ttl > 0s && (req.request == "GET" || req.request == "HEAD")) {
         unset beresp.http.set-cookie;
-        if (req.url !~ "\.(css|js|jpg|png|gif|tiff|bmp|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|woff)(\?|$)") {
+            if (req.url !~ "\.(ico|css|js|jpg|jpeg|png|gif|tiff|bmp|mp3|ogg|svg|swf|woff|woff2|eot|ttf|otf)(\?|$)") {
             set beresp.http.Pragma = "no-cache";
             set beresp.http.Expires = "-1";
             set beresp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0";
diff --git a/app/code/Magento/PageCache/etc/varnish4.vcl b/app/code/Magento/PageCache/etc/varnish4.vcl
index 5936fcd69255d03dbc70e6e34bf60282bda2dca5..0f3dddb893d95d123a74ef618183ddb6c9e8bbe0 100644
--- a/app/code/Magento/PageCache/etc/varnish4.vcl
+++ b/app/code/Magento/PageCache/etc/varnish4.vcl
@@ -47,7 +47,7 @@ sub vcl_recv {
     std.collect(req.http.Cookie);
 
     # static files are always cacheable. remove SSL flag and cookie
-    if (req.url ~ "^/(pub/)?(media|static)/.*\.(png|jpg|jpeg|gif|css|js|swf|ico|woff|svg)$") {
+        if (req.url ~ "^/(pub/)?(media|static)/.*\.(ico|css|js|jpg|jpeg|png|gif|tiff|bmp|mp3|ogg|svg|swf|woff|woff2|eot|ttf|otf)$") {
         unset req.http.Https;
         unset req.http.Cookie;
     }
@@ -90,7 +90,7 @@ sub vcl_backend_response {
     # images, css and js are cacheable by default so we have to remove cookie also
     if (beresp.ttl > 0s && (bereq.method == "GET" || bereq.method == "HEAD")) {
         unset beresp.http.set-cookie;
-        if (bereq.url !~ "\.(css|js|jpg|png|gif|tiff|bmp|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|woff)(\?|$)") {
+        if (bereq.url !~ "\.(ico|css|js|jpg|jpeg|png|gif|tiff|bmp|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|woff|woff2|eot|ttf|otf)(\?|$)") {
             set beresp.http.Pragma = "no-cache";
             set beresp.http.Expires = "-1";
             set beresp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0";
diff --git a/app/code/Magento/Ui/Component/Listing.php b/app/code/Magento/Ui/Component/Listing.php
index 1cfbaa1acd6f32b74a42ed67eff1b24472b41e80..6d8437a886c5e531522c59fe1fae4e13f7461ab3 100644
--- a/app/code/Magento/Ui/Component/Listing.php
+++ b/app/code/Magento/Ui/Component/Listing.php
@@ -188,7 +188,7 @@ class Listing extends AbstractView
     public function getCollectionItems()
     {
         $items = [];
-        $collection = $this->getDataCollection()->getResultCollection();
+        $collection = $this->getDataCollection();
         foreach ($collection->getItems() as $item) {
             $actualFields = [];
             $itemsData = $this->getDataFromDataProvider($item->getData());
@@ -230,8 +230,8 @@ class Listing extends AbstractView
         );
         $this->renderContext->getStorage()->addGlobalData('dump', ['extenders' => []]);
 
-        $collection = $this->getDataCollection()->getResultCollection();
-        $totalCount = $collection->getTotalCount();
+        $collection = $this->getDataCollection();
+        $totalCount = $collection->count();
         $this->renderContext->getStorage()->addDataSource(
             $this->getName(),
             [
diff --git a/app/code/Magento/Ui/Component/Paging.php b/app/code/Magento/Ui/Component/Paging.php
index 9a8f0a5ddd9b4eaedf2f144b484298eed0d0e301..7c504b74ac8303fff539ffe9671af8a9c68039e7 100644
--- a/app/code/Magento/Ui/Component/Paging.php
+++ b/app/code/Magento/Ui/Component/Paging.php
@@ -37,7 +37,10 @@ class Paging extends AbstractView
         $offset = $this->renderContext->getRequestParam('page', $defaultPage);
         $defaultLimit = $this->config->getData('pageSize');
         $size = $this->renderContext->getRequestParam('limit', $defaultLimit);
-        $this->renderContext->getStorage()->getDataCollection($this->getParentName())->setLimit($offset, $size);
+        $this->renderContext->getStorage()
+            ->getDataCollection($this->getParentName())
+            ->setPageSize($size)
+            ->setCurPage($offset);
     }
 
     /**
diff --git a/app/code/Magento/Ui/Test/Unit/Component/PagingTest.php b/app/code/Magento/Ui/Test/Unit/Component/PagingTest.php
index 68af1081739d613c26815a54088cc6e55a6ed431..e8cd28a27665a09b164e93c2f76c58e72ffd1ed7 100644
--- a/app/code/Magento/Ui/Test/Unit/Component/PagingTest.php
+++ b/app/code/Magento/Ui/Test/Unit/Component/PagingTest.php
@@ -153,7 +153,7 @@ class PagingTest extends \PHPUnit_Framework_TestCase
             false,
             true,
             true,
-            ['setLimit']
+            ['setPageSize', 'setCurPage']
         );
 
         $this->renderContextMock->expects($this->any())->method('getStorage')->willReturn($storageMock);
@@ -173,8 +173,12 @@ class PagingTest extends \PHPUnit_Framework_TestCase
             );
 
         $dataCollectionMock->expects($this->any())
-            ->method('setLimit')
-            ->with($paramsPage, $paramsSize)
+            ->method('setPageSize')
+            ->with($paramsSize)
+            ->willReturnSelf();
+        $dataCollectionMock->expects($this->any())
+            ->method('setCurPage')
+            ->with($paramsPage)
             ->willReturnSelf();
 
         $this->assertNull($this->view->prepare());
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less
index 0758cf95b23585ce288471dc71f6ad27a3ba9bb7..d8d0b25cb90f10fa092cc096fec35d72c733fce6 100644
--- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less
@@ -4,59 +4,82 @@
 //  */
 
 //
-//    Common
-//--------------------------------------
+//  Variables
+//  ---------------------------------------------
+
+@minicart__border-color: @color-gray80;
+@minicart__padding-horizontal: @indent__base;
+
+//
+//  Common
+//  ---------------------------------------------
 
 & when (@media-common = true) {
 
 //
-//    Minicart
-//--------------------------------------
+//  Minicart
+//  ---------------------------------------------
+
 .block-minicart {
     .items-total {
         float: left;
-        margin: 0 10px;
+        margin: 0 @indent__s;
+        .count {
+            font-weight: @font-weight__bold;
+        }
     }
     .subtotal {
-        margin: 0 10px;
+        margin: 0 @indent__s;
         text-align: right;
+        .label {
+            &:extend(.abs-colon all);
+        }
     }
     .amount {
-        .price-wrapper:first-child .price {
-            font-size: @font-size__l;
-            font-weight: @font-weight__bold;
+        .price-wrapper {
+            &:first-child {
+                .price {
+                    font-size: @font-size__l;
+                    font-weight: @font-weight__bold;
+                }
+            }
         }
     }
     .subtitle {
         display: none;
     }
-    .subtitle.empty {
-        display: block;
-        padding: 30px 0 20px;
-        text-align: center;
-        font-size: 14px;
+    .subtitle {
+        &.empty {
+            display: block;
+            padding: @indent__l 0 @indent__base;
+            text-align: center;
+            font-size: 14px;
+        }
     }
-    .empty.text {
-        text-align: center;
+    .text {
+        &.empty {
+            text-align: center;
+        }
     }
-    > .content > .actions {
-        margin-top: 15px;
-        text-align: center;
-        > .primary {
-            margin: 0 10px 15px;
-            .action.primary {
-                &:extend(.abs-button-l all);
-                display: block;
-                width: 100%;
-                margin-bottom: 15px;
-                &:last-child {
-                    margin-bottom: 0;
+    .block-content {
+        > .actions {
+            margin-top: 15px;
+            text-align: center;
+            > .primary {
+                margin: 0 @indent__s 15px;
+                .action {
+                    &.primary {
+                        &:extend(.abs-button-l all);
+                        display: block;
+                        width: 100%;
+                        margin-bottom: 15px;
+                        &:last-child {
+                            margin-bottom: 0;
+                        }
+                    }
                 }
             }
         }
-        > .secondary {
-            margin: 0 0 15px;
-        }
     }
     .block-category-link,
     .block-product-link,
@@ -84,10 +107,10 @@
     );
     float: right;
     .block-minicart {
-        padding: 25px 20px;
+        .css(padding, 25px @minicart__padding-horizontal);
         right: 0;
         width: 320px;
-        > .title {
+        .block-title {
             display: none;
         }
         &:after {
@@ -104,95 +127,138 @@
         > .primary,
         > .secondary {
             display: inline;
-            margin-right: @indent__s;
-            &:last-child {
-                margin-right: 0;
-            }
         }
     }
-    .action.close {
-        display: none;
-    }
-    .action.showcart {
-        .text {
-            &:extend(.abs-visually-hidden all);
+
+    .action {
+        &.close {
+            width: 40px;
+            height: 40px;
+            top: 0;
+            right: 0;
+            position: absolute;
+            .button-reset();
+            .button-icon(
+                @icon-remove,
+                @_icon-font-size: 32px,
+                @_icon-font-line-height: 32px,
+                @_icon-font-text-hide: true
+            );
         }
-        white-space: nowrap;
-        .counter.qty {
-            &.empty {
-               display: none;
+        &.showcart {
+            .text {
+                &:extend(.abs-visually-hidden all);
+            }
+            white-space: nowrap;
+            .counter.qty {
+                &.empty {
+                   display: none;
+                }
+                .css(background, @active__color);
+                border-radius: 2px;
+                .css(color, @page__background-color);
+                clip: none;
+                display: inline-block;
+                height: 24px;
+                line-height: 24px;
+                min-width: 18px;
+                margin: 3px 0 0;
+                padding: 0 3px;
+                overflow: hidden;
+                text-align: center;
+                white-space: normal;
+            }
+            .counter-label {
+                &:extend(.abs-visually-hidden all);
             }
-            .css(background, @active__color);
-            border-radius: 2px;
-            .css(color, @page__background-color);
-            clip: none;
-            display: inline-block;
-            height: 24px;
-            line-height: 24px;
-            min-width: 18px;
-            margin: 3px 0 0;
-            padding: 0 3px;
-            overflow: hidden;
-            text-align: center;
-            white-space: normal;
-        }
-        .counter-label {
-            &:extend(.abs-visually-hidden all);
         }
     }
+    .minicart-widgets {
+        margin-top: 15px;
+    }
+}
+
+.minicart-items-wrapper {
+    .css(border, 1px solid @minicart__border-color);
+    .css(margin, 0 -@minicart__padding-horizontal);
+    border-left: 0;
+    border-right: 0;
+    overflow-x: auto;
+    padding: 15px;
 }
 
-.minilist {
+.minicart-items {
     .list-reset-styles(0, 0);
     .item {
-        border-top: 1px solid @secondary__color;
-        padding: 20px 0;
-        z-index: 1;
-    }
-    .item > .product {
-        &:extend(.abs-add-clearfix all);
+        &:not(:first-child) {
+            .css(border-top, 1px solid @minicart__border-color);
+        }
+        padding: @indent__base 0;
+        &:first-child {
+            padding-top: 0;
+        }
+        &:last-child {
+            padding-bottom: 0;
+        }
+        > .product {
+            &:extend(.abs-add-clearfix all);
+        }
     }
     .product-image-wrapper {
         &:extend(.abs-reset-image-wrapper all);
     }
-    .product {
-        &-item-photo {
-            float: left;
-        }
-        &-item-name {
-            font-weight: @font-weight__regular;
-            margin-top: 0;
-            a {
-                .css(color, @link__color);
-            }
+    .product-item-pricing {
+        .label {
+            display: inline-block;
+            width: 4.5rem;
+         }
+    }
+    .price-minicart {
+        margin-bottom: @indent__xs;
+    }
+    .product-item-photo {
+        float: left;
+    }
+    .product-item-name {
+        font-weight: @font-weight__regular;
+        margin: 0 0 @indent__s;
+        a {
+            .css(color, @link__color);
         }
-        &-item-details {
-            padding-left: 88px;
-            .price {
-                font-weight: @font-weight__bold;
-            }
+    }
+    .product-item-details {
+        padding-left: 88px;
+        .price {
+            font-weight: @font-weight__bold;
         }
-        &.pricing {
-            margin-top: 3px;
-        }
-        &.options {
-            .tooltip.toggle {
-                .icon-font(
-                    @icon-down,
-                    @_icon-font-size: 28px,
-                    @_icon-font-line-height: 28px,
-                    @_icon-font-text-hide: true,
-                    @_icon-font-margin: -3px 0 0 7px,
-                    @_icon-font-position: after
-                );
-            }
+    }
+    .product.options {
+        .tooltip.toggle {
+            .icon-font(
+                @icon-down,
+                @_icon-font-size: 28px,
+                @_icon-font-line-height: 28px,
+                @_icon-font-text-hide: true,
+                @_icon-font-margin: -3px 0 0 7px,
+                @_icon-font-position: after
+            );
         }
     }
-    .details-qty {
-        .label:after {
-            content: ":";
+    .details-qty,
+    .price-minicart {
+        .label {
+            &:extend(.abs-colon all);
         }
     }
+    .item-qty {
+        width: 40px;
+        text-align: center;
+        margin-right: @indent__s;
+    }
+    .item-update {
+        vertical-align: top;
+        .font-size(11);
+    }
     .action {
          &.edit,
          &.delete {
@@ -217,8 +283,9 @@
 }
 
 //
-//    Mobile
-//--------------------------------------
+//  Mobile
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__xs) {
     .minicart-wrapper .block-minicart {
         width: 290px;
@@ -232,8 +299,9 @@
 }
 
 //
-//    Desktop
-//--------------------------------------
+//  Desktop
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
     .minicart-wrapper {
         margin-left: 13px;
diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less
index 655c892d6dc9fff3b743a6ef799a617fd02c9a9d..3a65f3be3f3055aca8770b2ec9b94145206a63fc 100644
--- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less
+++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less
@@ -4,58 +4,83 @@
 //  */
 
 //
-//    Common
-//--------------------------------------
+//  Variables
+//  ---------------------------------------------
+
+@minicart__border-color: @color-gray80;
+@minicart__padding-horizontal: @indent__base;
+
+//
+//  Common
+//  ---------------------------------------------
 
 & when (@media-common = true) {
 
 //
-//    Minicart
-//--------------------------------------
+//  Minicart
+//  ---------------------------------------------
+
 .block-minicart {
     .items-total {
         float: left;
-        margin: 0 10px;
+        margin: 0 @indent__s;
+        .count {
+            font-weight: @font-weight__bold;
+        }
     }
     .subtotal {
-        margin: 0 10px;
+        margin: 0 @indent__s;
         text-align: right;
+        .label {
+            &:extend(.abs-colon all);
+        }
     }
     .amount {
-        .price-wrapper:first-child .price {
-            font-size: @font-size__l;
-            font-weight: @font-weight__bold;
+        .price-wrapper {
+            &:first-child {
+                .price {
+                    font-size: @font-size__l;
+                    font-weight: @font-weight__bold;
+                }
+            }
         }
     }
     .subtitle {
         display: none;
     }
-    .subtitle.empty {
-        display: block;
-        padding: 30px 0 20px;
-        text-align: center;
-        font-size: 14px;
-    }
-    .empty.text {
-        text-align: center;
-    }
-    > .content > .actions {
-        margin-top: 15px;
-        > .secondary {
-            margin: 15px 0;
+    .subtitle {
+        &.empty {
+            display: block;
+            padding: @indent__l 0 @indent__base;
             text-align: center;
+            font-size: 14px;
         }
-        > .primary {
-            margin: 0 10px;
-            .action.primary {
-                &:extend(.abs-button-l all);
-                display: block;
-                width: 100%;
-            }
+    }
+    .text {
+        &.empty {
+            text-align: center;
         }
-        .paypal-logo {
+    }
+    .block-content {
+        > .actions {
             margin-top: 15px;
-            text-align: center;
+            > .secondary {
+                text-align: center;
+            }
+            > .primary {
+                margin: 0 @indent__s 15px;
+                .action {
+                    &.primary {
+                        &:extend(.abs-button-l all);
+                        display: block;
+                        width: 100%;
+                    }
+                }
+            }
+            .paypal-logo {
+                margin-top: 15px;
+                text-align: center;
+            }
         }
     }
     .block-category-link,
@@ -84,10 +109,10 @@
     );
     float: right;
     .block-minicart {
-        padding: 25px 20px;
+        .css(padding, 25px @minicart__padding-horizontal);
         right: 0;
         width: 320px;
-        > .title {
+        .block-title {
             display: none;
         }
         &:after {
@@ -99,77 +124,123 @@
             right: 26px;
         }
     }
-    .product.actions {
-        float: right;
-        margin: -24px 0 0;
-        > .primary,
-        > .secondary {
-            display: inline;
+    .product {
+        .actions {
+            float: right;
+            margin: -24px 0 0;
+            > .primary,
+            > .secondary {
+                display: inline;
+                &:not(:last-child) {
+                    margin-right: 15px;
+                }
+            }
         }
     }
-    .action.close {
-        display: none;
-    }
-    .action.showcart {
-        .text {
-            &:extend(.abs-visually-hidden all);
+    .action {
+        &.close {
+            width: 40px;
+            height: 40px;
+            top: 0;
+            right: 0;
+            position: absolute;
+            .button-reset();
+            .button-icon(
+                @icon-remove,
+                @_icon-font-color: @minicart-icons-color,
+                @_icon-font-size: 16px,
+                @_icon-font-line-height: 16px,
+                @_icon-font-text-hide: true
+            );
         }
-        white-space: nowrap;
-        .counter.qty {
-            &.empty {
-               display: none;
+        &.showcart {
+            .text {
+                &:extend(.abs-visually-hidden all);
+            }
+            white-space: nowrap;
+            .counter.qty {
+                &.empty {
+                   display: none;
+                }
+                .css(background, @active__color);
+                border-radius: 2px;
+                .css(color, @page__background-color);
+                clip: none;
+                display: inline-block;
+                height: 24px;
+                line-height: 24px;
+                min-width: 18px;
+                margin: 3px 0 0;
+                padding: 0 3px;
+                overflow: hidden;
+                text-align: center;
+                white-space: normal;
+            }
+            .counter-label {
+                &:extend(.abs-visually-hidden all);
             }
-            .css(background, @active__color);
-            border-radius: 2px;
-            .css(color, @page__background-color);
-            clip: none;
-            display: inline-block;
-            height: 24px;
-            line-height: 24px;
-            min-width: 18px;
-            margin: 3px 0 0;
-            padding: 0 3px;
-            overflow: hidden;
-            text-align: center;
-            white-space: normal;
-        }
-        .counter-label {
-            &:extend(.abs-visually-hidden all);
         }
     }
+    .minicart-widgets {
+        margin-top: 15px;
+    }
 }
 
-.minilist {
+.minicart-items-wrapper {
+    .css(border, 1px solid @minicart__border-color);
+    .css(margin, 0 -@minicart__padding-horizontal);
+    border-left: 0;
+    border-right: 0;
+    overflow-x: auto;
+    padding: 15px;
+}
+
+.minicart-items {
     .list-reset-styles(0, 0);
     .item {
-        border-top: 1px solid @secondary__color;
-        padding: 20px 0;
-        z-index: 1;
-    }
-
-    .item > .product {
-        &:extend(.abs-add-clearfix all);
+        &:not(:first-child) {
+            .css(border-top, 1px solid @minicart__border-color);
+        }
+        padding: @indent__base 0;
+        &:first-child {
+            padding-top: 0;
+        }
+        &:last-child {
+            padding-bottom: 0;
+        }
+        > .product {
+            &:extend(.abs-add-clearfix all);
+        }
     }
     .product-image-wrapper {
         &:extend(.abs-reset-image-wrapper all);
     }
-    .product {
-        &-item-photo {
-            float: left;
+    .product-item-pricing {
+        .label {
+            display: inline-block;
+            width: 4.5rem;
         }
-        &-item-name {
-            font-weight: @font-weight__regular;
-            margin-top: 0;
-            a {
-                .css(color, @link__color);
-            }
+    }
+    .price-minicart {
+        margin-bottom: @indent__xs;
+    }
+    .product-item-photo {
+        float: left;
+    }
+    .product-item-name {
+        font-weight: @font-weight__regular;
+        margin: 0 0 @indent__s;
+        a {
+            .css(color, @link__color);
         }
-        &-item-details {
-            padding-left: 88px;
-            .price {
-                font-weight: @font-weight__bold;
-            }
+    }
+    .product-item-details {
+        padding-left: 88px;
+        .price {
+            font-weight: @font-weight__bold;
         }
+    }
+    .product {
         .toggle {
             &:extend(.abs-toggling-title all);
             &:after {
@@ -179,7 +250,6 @@
             }
             border: 0;
             padding: 0 @indent__xl @indent__xs 0;
-
         }
         .active {
             > .toggle {
@@ -205,12 +275,21 @@
             }
         }
     }
-    .details-qty {
-        .label:after {
-            content: ":";
+    .details-qty,
+    .price-minicart {
+        .label {
+            &:extend(.abs-colon all);
         }
     }
-
+    .item-qty {
+        width: 40px;
+        text-align: center;
+        margin-right: @indent__s;
+    }
+    .update-cart-item {
+        vertical-align: top;
+        .font-size(11);
+    }
     .action {
         &.edit,
         &.delete {
@@ -235,8 +314,9 @@
 }
 
 //
-//    Mobile
-//--------------------------------------
+//  Mobile
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__xs) {
     .minicart-wrapper .block-minicart {
         width: 290px;
@@ -249,9 +329,11 @@
     }
 }
 
+
 //
-//    Desktop
-//--------------------------------------
+//  Desktop
+//  ---------------------------------------------
+
 .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
     .minicart-wrapper {
         margin-left: 13px;
diff --git a/dev/tests/functional/bootstrap.php b/dev/tests/functional/bootstrap.php
index b661b84d1ceccd96c2b4ceb28ee3ee9ff0d31dc2..5a4f9a7c490dee281665493f4eea214c77d2d4ca 100644
--- a/dev/tests/functional/bootstrap.php
+++ b/dev/tests/functional/bootstrap.php
@@ -4,7 +4,6 @@
  * See COPYING.txt for license details.
  */
 
-session_start();
 defined('MTF_BOOT_FILE') || define('MTF_BOOT_FILE', __FILE__);
 defined('MTF_BP') || define('MTF_BP', str_replace('\\', '/', (__DIR__)));
 require_once __DIR__ . '/../../../app/bootstrap.php';
diff --git a/dev/tests/functional/composer.json b/dev/tests/functional/composer.json
index 256e8f34c43778f4f2ff4f4feabb4b5c20547524..41482866c1b241dbf0feb2c100d029ed51e11d68 100644
--- a/dev/tests/functional/composer.json
+++ b/dev/tests/functional/composer.json
@@ -1,6 +1,6 @@
 {
     "require": {
-        "magento/mtf": "1.0.0-rc20",
+        "magento/mtf": "1.0.0-rc21",
         "php": "~5.5.0|~5.6.0",
         "phpunit/phpunit": "4.1.0",
         "phpunit/phpunit-selenium": ">=1.2",
diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php
index c4b2a9d7f85cc2649fbe9c95f71063f5c9de7115..ff02e15272bd9dc13e0a1c1f58e445024d06c469 100644
--- a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php
+++ b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php
@@ -6,7 +6,7 @@
 
 namespace Magento\Mtf\Util\Protocol\CurlTransport;
 
-use Magento\Mtf\Config;
+use Magento\Mtf\Config\DataInterface;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 
@@ -40,7 +40,7 @@ class BackendDecorator implements CurlInterface
     /**
      * System config
      *
-     * @var Config
+     * @var DataInterface
      */
     protected $configuration;
 
@@ -48,9 +48,9 @@ class BackendDecorator implements CurlInterface
      * Constructor
      *
      * @param CurlTransport $transport
-     * @param Config $configuration
+     * @param DataInterface $configuration
      */
-    public function __construct(CurlTransport $transport, Config $configuration)
+    public function __construct(CurlTransport $transport, DataInterface $configuration)
     {
         $this->transport = $transport;
         $this->configuration = $configuration;
@@ -65,11 +65,10 @@ class BackendDecorator implements CurlInterface
      */
     protected function authorize()
     {
-        $url = $_ENV['app_backend_url'] .
-            $this->configuration->getParameter('application/backendLoginUrl');
+        $url = $_ENV['app_backend_url'] . $this->configuration->get('application/0/backendLoginUrl/0/value');
         $data = [
-            'login[username]' => $this->configuration->getParameter('application/backendLogin'),
-            'login[password]' => $this->configuration->getParameter('application/backendPassword'),
+            'login[username]' => $this->configuration->get('application/0/backendLogin/0/value'),
+            'login[password]' => $this->configuration->get('application/0/backendPassword/0/value'),
         ];
         $this->transport->write(CurlInterface::POST, $url, '1.0', [], $data);
         $response = $this->read();
diff --git a/dev/tests/functional/phpunit.xml.dist b/dev/tests/functional/phpunit.xml.dist
index 06b2ee9b0603d8fd6e602011e34ddbf2b131c00f..f99b813aa1073903e64d1495ea27d55440cd3547 100755
--- a/dev/tests/functional/phpunit.xml.dist
+++ b/dev/tests/functional/phpunit.xml.dist
@@ -26,7 +26,6 @@
             </arguments>
         </listener>
         <listener class="Magento\Mtf\System\Event\StateListener" />
-        <listener class="Magento\Mtf\System\JUnit"/>
     </listeners>
 
     <php>
@@ -37,7 +36,6 @@
         <env name="log_directory" value="var/log" />
         <env name="events_preset" value="base" />
         <env name="module_whitelist" value="Magento_Install,Magento_Core" />
-        <env name="report_file_name" value="test-cases-report.xml"/>
         <env name="basedir" value="var/log" />
         <env name="credentials_file_path" value="./credentials.xml.dist" />
     </php>
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Fixture/Admin/SuperAdmin.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Fixture/Admin/SuperAdmin.php
index fd1a66d884fbecb34528b214b112ad0afa7741ca..3d18543896556fd8cd86604348c2ce5da1650900 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Fixture/Admin/SuperAdmin.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Fixture/Admin/SuperAdmin.php
@@ -22,10 +22,10 @@ class SuperAdmin extends DataFixture
         $this->_data = [
             'fields' => [
                 'username' => [
-                    'value' => $this->_configuration->getParameter('application/backendLogin'),
+                    'value' => $this->_configuration->get('application/0/backendLogin/0/value'),
                 ],
                 'password' => [
-                    'value' => $this->_configuration->getParameter('application/backendPassword'),
+                    'value' => $this->_configuration->get('application/0/backendPassword/0/value'),
                 ],
             ],
         ];
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Fixture/GlobalSearch.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/Fixture/GlobalSearch.xml
index e40e21c4fca28b00ba54d39c6bd30bd66f20f241..7b1c3f2aeac1d2d0f6e9be43c3dab50609066d32 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Fixture/GlobalSearch.xml
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Fixture/GlobalSearch.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="globalSearch" module="Magento_Backend" class="Magento\Backend\Test\Fixture\GlobalSearch">
     <dataset name="default">
         <field name="query" xsi:type="string">catalogProductSimple::default::name</field>
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Handler/Extractor.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Handler/Extractor.php
index 967d142da277c2cb30be1ff7927363b03caf93a5..3df57e717b29304175d27a3fc9c66f4cb3cd9456 100755
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Handler/Extractor.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Handler/Extractor.php
@@ -7,7 +7,6 @@
 
 namespace Magento\Backend\Test\Handler;
 
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
@@ -62,8 +61,8 @@ class Extractor
      */
     public function getData()
     {
-        /** @var \Magento\Mtf\Config $config */
-        $config = \Magento\Mtf\ObjectManagerFactory::getObjectManager()->get('Magento\Mtf\Config');
+        /** @var \Magento\Mtf\Config\DataInterface $config */
+        $config = \Magento\Mtf\ObjectManagerFactory::getObjectManager()->get('Magento\Mtf\Config\DataInterface');
         $url = $_ENV['app_backend_url'] . $this->url;
         $curl = new BackendDecorator(new CurlTransport(), $config);
         $curl->addOption(CURLOPT_HEADER, 1);
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleProduct.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleProduct.xml
index 6b345b542bb84bbdcfcfe6bd9ced8353fa68228f..b9f96e1cb55a7ff19150c846a5424c9b8a2c4414 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleProduct.xml
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleProduct.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="bundleProduct" module="Magento_Bundle" type="eav" entity_type="catalog_product" product_type="bundle" collection="Magento\Catalog\Model\Resource\Product\Collection" identifier="sku" repository_class="Magento\Bundle\Test\Repository\BundleProduct" handler_interface="Magento\Bundle\Test\Handler\BundleProduct\BundleProductInterface" class="Magento\Bundle\Test\Fixture\BundleProduct">
     <dataset name="default">
         <field name="name" xsi:type="string">BundleProduct %isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/BundleProduct/Curl.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/BundleProduct/Curl.php
index cbd47bd232e4ea5fd3f79bc667b3f73084b37eb2..6eeb06506c9cd342adeea36c2426cb964edaf6de 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/BundleProduct/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/BundleProduct/Curl.php
@@ -9,7 +9,8 @@ namespace Magento\Bundle\Test\Handler\BundleProduct;
 use Magento\Bundle\Test\Fixture\BundleProduct;
 use Magento\Catalog\Test\Handler\CatalogProductSimple\Curl as ProductCurl;
 use Magento\Mtf\Fixture\FixtureInterface;
-use Magento\Mtf\Config;
+use Magento\Mtf\Config\DataInterface;
+use Magento\Mtf\System\Event\EventManagerInterface;
 
 /**
  * Create new bundle product via curl.
@@ -25,11 +26,12 @@ class Curl extends ProductCurl implements BundleProductInterface
 
     /**
      * @constructor
-     * @param Config $configuration
+     * @param DataInterface $configuration
+     * @param EventManagerInterface $eventManager
      */
-    public function __construct(Config $configuration)
+    public function __construct(DataInterface $configuration, EventManagerInterface $eventManager)
     {
-        parent::__construct($configuration);
+        parent::__construct($configuration, $eventManager);
 
         $this->mappingData += [
             'selection_can_change_qty' => [
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogAttributeSet.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogAttributeSet.xml
index e30dafaff1c5a7eb1c90af347f40e670e8fe4b6e..20c3c831f6e627016d8ff8f74fff0f8d26485017 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogAttributeSet.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogAttributeSet.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
     <fixture name="catalogAttributeSet" module="Magento_Catalog" type="flat" entity_type="eav_attribute_set" collection="Magento\Catalog\Model\Resource\Product\Link\Product\Collection" repository_class="Magento\Catalog\Test\Repository\CatalogAttributeSet" handler_interface="Magento\Catalog\Test\Handler\CatalogAttributeSet\CatalogAttributeSetInterface" class="Magento\Catalog\Test\Fixture\CatalogAttributeSet">
     <dataset name="default">
         <field name="attribute_set_name" xsi:type="string">Default_attribute_set_%isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductAttribute.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductAttribute.xml
index 0a33bf96c60d635bad7e1cff10fa6da4f6f646b4..1e99a0752d4e407a6dfac02c519cf83d9f6ded54 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductAttribute.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductAttribute.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="catalogProductAttribute" module="Magento_Catalog" type="composite" collection="Magento\Catalog\Model\Resource\Attribute" repository_class="Magento\Catalog\Test\Repository\CatalogProductAttribute" handler_interface="Magento\Catalog\Test\Handler\CatalogProductAttribute\CatalogProductAttributeInterface" class="Magento\Catalog\Test\Fixture\CatalogProductAttribute">
     <dataset name="default">
         <field name="frontend_label" xsi:type="string">attribute_label%isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml
index 1815359930d5d7827cd2ce06681b12c7da7f60a0..59bc10f7eeecdc84fcec704f0166306b479f60f5 100755
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="catalogProductSimple" module="Magento_Catalog" type="eav" entity_type="catalog_product" product_type="simple" collection="Magento\Catalog\Model\Resource\Product\Collection" identifier="sku" repository_class="Magento\Catalog\Test\Repository\CatalogProductSimple" handler_interface="Magento\Catalog\Test\Handler\CatalogProductSimple\CatalogProductSimpleInterface" class="Magento\Catalog\Test\Fixture\CatalogProductSimple">
     <dataset name="default">
         <field name="name" xsi:type="string">Test simple product %isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TaxClass.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TaxClass.php
index 8ca245b0c1607022eb2da61b21028f5efd077404..7bc605d82acca354327d119a88a570982aec88a4 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TaxClass.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TaxClass.php
@@ -9,7 +9,6 @@ namespace Magento\Catalog\Test\Fixture\CatalogProductSimple;
 use Magento\Tax\Test\Fixture\TaxClass as FixtureTaxClass;
 use Magento\Mtf\Fixture\FixtureFactory;
 use Magento\Mtf\Fixture\FixtureInterface;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
@@ -89,7 +88,7 @@ class TaxClass implements FixtureInterface
     protected function setTaxClassId($taxClassName)
     {
         $url = $_ENV['app_backend_url'] . 'tax/rule/new/';
-        $config = \Magento\Mtf\ObjectManagerFactory::getObjectManager()->create('Magento\Mtf\Config');
+        $config = \Magento\Mtf\ObjectManagerFactory::getObjectManager()->create('Magento\Mtf\Config\DataInterface');
         $curl = new BackendDecorator(new CurlTransport(), $config);
         $curl->addOption(CURLOPT_HEADER, 1);
         $curl->write(CurlInterface::POST, $url, '1.0', [], []);
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.xml
index fd551f743f338cc4b096d7085084070cc2a144a5..158e62ce41f722ec50d060011baf95da903f15f9 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="catalogProductVirtual" module="Magento_Catalog" type="eav" entity_type="catalog_product" product_type="virtual" collection="Magento\Catalog\Model\Resource\Product\Collection" identifier="sku" repository_class="Magento\Catalog\Test\Repository\CatalogProductVirtual" handler_interface="Magento\Catalog\Test\Handler\CatalogProductVirtual\CatalogProductVirtualInterface" class="Magento\Catalog\Test\Fixture\CatalogProductVirtual">
     <dataset name="default">
         <field name="name" xsi:type="string">Test virtual product %isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Category.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Category.xml
index 663a249b5da66e367bd8b0a953e622653aaa065e..9ea63b5e3616f573ba5385f127969f81779f8210 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Category.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Category.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="category" module="Magento_Catalog" type="eav" entity_type="catalog_category_entity" collection="Magento\Catalog\Model\Resource\Category\Collection" repository_class="Magento\Catalog\Test\Repository\Category" handler_interface="Magento\Catalog\Test\Handler\Category\CategoryInterface" class="Magento\Catalog\Test\Fixture\Category">
     <dataset name="default">
         <field name="name" xsi:type="string">Category%isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogAttributeSet/Curl.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogAttributeSet/Curl.php
index 8c7e5905afb7339488389ab62caeedc929ecd784..b5f8585e01fe459e6f67529a6683c2c3281ddba8 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogAttributeSet/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogAttributeSet/Curl.php
@@ -9,7 +9,6 @@ namespace Magento\Catalog\Test\Handler\CatalogAttributeSet;
 use Magento\Catalog\Test\Fixture\CatalogAttributeSet;
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php
index 123ef506c991ee390aedc790ce8f2e58fd8224e1..1e7ec99e39fe2fec29869f7faa934711cab988b0 100755
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php
@@ -405,7 +405,8 @@ class Curl extends AbstractCurl implements CatalogProductSimpleInterface
         $curl->close();
 
         if (!strpos($response, 'data-ui-id="messages-message-success"')) {
-            throw new \Exception("Product creation by curl handler was not successful! Response: $response");
+            $this->_eventManager->dispatchEvent(['curl_failed'], [$response]);
+            throw new \Exception('Product creation by curl handler was not successful!');
         }
 
         return $this->parseResponse($response);
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Category/Curl.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Category/Curl.php
index 9770e6726048c6139631ba6022d8801484e1c108..e684946a46f47f152fdd1d4373f31a31b1142dd4 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Category/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Category/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\Catalog\Test\Handler\Category;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Curl/CreateProductAttribute.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Curl/CreateProductAttribute.php
index 6353c542d857e57541d700b0d9ad45d17e3a7a35..632de082cfe61df3dcfddd9ccf1359a9d3581638 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Curl/CreateProductAttribute.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Curl/CreateProductAttribute.php
@@ -9,7 +9,6 @@ namespace Magento\Catalog\Test\Handler\Curl;
 use Magento\Catalog\Test\Fixture\ProductAttribute;
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Fixture/CatalogRule.xml b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Fixture/CatalogRule.xml
index 073335f8ab0ff6b5aa04801c6d30489a51ac9ba5..88c2147c46a54c83273e0ebe386af6f4e3bf39a9 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Fixture/CatalogRule.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Fixture/CatalogRule.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="catalogRule" module="Magento_CatalogRule" type="eav" entity_type="catalog_rule" collection="Magento\CatalogRule\Model\Resource\Rule\Product\Price\Collection" repository_class="Magento\CatalogRule\Test\Repository\CatalogRule" handler_interface="Magento\CatalogRule\Test\Handler\CatalogRule\CatalogRuleInterface" class="Magento\CatalogRule\Test\Fixture\CatalogRule">
     <dataset name="default">
         <field name="name" xsi:type="string">CatalogPriceRule %isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Handler/CatalogRule/Curl.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Handler/CatalogRule/Curl.php
index 1c6d9a58f87105e992b2e1572477ef0085f32b6c..43089928c2c50da39f1c589cdb05a31ba4b6dc96 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Handler/CatalogRule/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Handler/CatalogRule/Curl.php
@@ -9,7 +9,6 @@ namespace Magento\CatalogRule\Test\Handler\CatalogRule;
 use Magento\Backend\Test\Handler\Conditions;
 use Magento\CatalogRule\Test\Handler\CatalogRule;
 use Magento\Mtf\Fixture\FixtureInterface;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Fixture/CatalogSearchQuery.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Fixture/CatalogSearchQuery.xml
index 59b4b4ee904fa40efd1b4a71bc46a437543e8d74..940729a21995ef1db6dd3a718c6c92293ddbe299 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Fixture/CatalogSearchQuery.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Fixture/CatalogSearchQuery.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="catalogSearchQuery" module="Magento_CatalogSearch" type="flat" entity_type="search_query" collection="Magento\Search\Model\Resource\Query\Collection" repository_class="Magento\CatalogSearch\Test\Repository\CatalogSearchQuery" handler_interface="Magento\CatalogSearch\Test\Handler\CatalogSearchQuery\CatalogSearchQueryInterface" class="Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery">
     <field name="query_id" is_required="1">
       <default_value xsi:type="null"/>
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Handler/CatalogSearchQuery/Curl.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Handler/CatalogSearchQuery/Curl.php
index 049e2e77a7d47967f1cc79cb7339c9ac17d63b0c..3381fe268097374df309f6d511e2b8fa7750747f 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Handler/CatalogSearchQuery/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Handler/CatalogSearchQuery/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\CatalogSearch\Test\Handler\CatalogSearchQuery;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Fixture/Cart.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/Fixture/Cart.xml
index 564e190e5f0f65b62786e16a4164e7e360617577..9c79804bfe3b25fd4bbe857f9f17c46fe9da2e08 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Fixture/Cart.xml
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Fixture/Cart.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="cart" module="Magento_Checkout" type="flat" entity_type="quote" repository_class="Magento\Checkout\Test\Repository\Cart" handler_interface="Magento\Checkout\Test\Handler\Cart\CartInterface" class="Magento\Checkout\Test\Fixture\Cart">
     <field name="entity_id" is_required="1">
       <default_value xsi:type="null"/>
diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Fixture/CheckoutAgreement.xml b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Fixture/CheckoutAgreement.xml
index 4a9a438e8460ae93d277273787204e0d78bfd333..d1f5018824ca4b96d33cf487ce339c285c1022f5 100644
--- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Fixture/CheckoutAgreement.xml
+++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Fixture/CheckoutAgreement.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
     <fixture name="checkoutAgreement" module="Magento_CheckoutAgreements"
              type="flat" entity_type="checkout_agreement" collection="Magento\CheckoutAgreements\Model\Resource\Agreement\Collection"
              repository_class="Magento\CheckoutAgreements\Test\Repository\CheckoutAgreement"
diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Handler/CheckoutAgreement/Curl.php b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Handler/CheckoutAgreement/Curl.php
index 426831f470e92ed668e07a121bdc21fe1f2f1d07..9c241ef1354cd41eea088125162a1fe2b80df565 100644
--- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Handler/CheckoutAgreement/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Handler/CheckoutAgreement/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\CheckoutAgreements\Test\Handler\CheckoutAgreement;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Fixture/CmsBlock.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/Fixture/CmsBlock.xml
index 36bb9cf39af0421b3a0bc9e6e25115cb312ad55e..5d1a718ff1178b9a4737c8bbcc3df08f9e79accf 100644
--- a/dev/tests/functional/tests/app/Magento/Cms/Test/Fixture/CmsBlock.xml
+++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Fixture/CmsBlock.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
     <fixture name="cmsBlock" module="Magento_Cms" type="flat" entity_type="cms_block" collection="Magento\Cms\Model\Resource\Block\Grid\Collection" identifier="identifier"
              handler_interface="Magento\Cms\Test\Handler\CmsBlock\CmsBlockInterface" class="Magento\Cms\Test\Fixture\CmsBlock">
         <dataset name="default">
diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Fixture/CmsPage.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/Fixture/CmsPage.xml
index 149bef091c83163e09710dbaa2cd7f4bc6930058..071897f0c5b13b72147ac1b674931f71e784f333 100644
--- a/dev/tests/functional/tests/app/Magento/Cms/Test/Fixture/CmsPage.xml
+++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Fixture/CmsPage.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
     <fixture name="cmsPage" module="Magento_Cms" type="flat" entity_type="cms_page" collection="Magento\Cms\Model\Resource\Page\Grid\Collection" identifier="identifier"
              repository_class="Magento\Cms\Test\Repository\CmsPage" handler_interface="Magento\Cms\Test\Handler\CmsPage\CmsPageInterface" class="Magento\Cms\Test\Fixture\CmsPage">
         <dataset name="default">
diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsBlock/Curl.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsBlock/Curl.php
index c3aefd941fc29abf6f5b823497131213d235f6ed..05564ee03f0572909f449a17b07910d1f4d54234 100644
--- a/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsBlock/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsBlock/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\Cms\Test\Handler\CmsBlock;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsPage/Curl.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsPage/Curl.php
index 4187350d28d7aead4044c949f745be6968cf1a17..a91b23ff28b1bba3b0802c4a3881a041e0517008 100644
--- a/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsPage/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsPage/Curl.php
@@ -8,7 +8,8 @@ namespace Magento\Cms\Test\Handler\CmsPage;
 
 use Magento\Backend\Test\Handler\Conditions;
 use Magento\Mtf\Fixture\FixtureInterface;
-use Magento\Mtf\Config;
+use Magento\Mtf\Config\DataInterface;
+use Magento\Mtf\System\Event\EventManagerInterface;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
@@ -55,12 +56,13 @@ class Curl extends Conditions implements CmsPageInterface
 
     /**
      * @constructor
-     * @param Config $configuration
+     * @param DataInterface $configuration
+     * @param EventManagerInterface $eventManager
      */
-    public function __construct(Config $configuration)
+    public function __construct(DataInterface $configuration, EventManagerInterface $eventManager)
     {
         $this->mappingData = array_merge($this->mappingData, $this->additionalMappingData);
-        parent::__construct($configuration);
+        parent::__construct($configuration, $eventManager);
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct.xml
index 839a00ef4a8074e7da8e5f7e59398ac5a578a3a7..6eb5ee6976ace67bf42136395b5894d354f7618c 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct.xml
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="configurableProduct"
            module="Magento_ConfigurableProduct" 
            type="eav" 
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Handler/ConfigurableProduct/Curl.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Handler/ConfigurableProduct/Curl.php
index 1bed329a243d055bce4df0c0a5a19b997806a639..7e0813eca10a21cbce34254bfd1eb9e3dafecb20 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Handler/ConfigurableProduct/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Handler/ConfigurableProduct/Curl.php
@@ -10,7 +10,8 @@ use Magento\Catalog\Test\Fixture\CatalogProductAttribute;
 use Magento\Catalog\Test\Handler\CatalogProductSimple\Curl as ProductCurl;
 use Magento\ConfigurableProduct\Test\Fixture\ConfigurableProduct\ConfigurableAttributesData;
 use Magento\Mtf\Fixture\FixtureInterface;
-use Magento\Mtf\Config;
+use Magento\Mtf\Config\DataInterface;
+use Magento\Mtf\System\Event\EventManagerInterface;
 
 /**
  * Class Curl
@@ -21,11 +22,12 @@ class Curl extends ProductCurl implements ConfigurableProductInterface
     /**
      * Constructor
      *
-     * @param Config $configuration
+     * @param DataInterface $configuration
+     * @param EventManagerInterface $eventManager
      */
-    public function __construct(Config $configuration)
+    public function __construct(DataInterface $configuration, EventManagerInterface $eventManager)
     {
-        parent::__construct($configuration);
+        parent::__construct($configuration, $eventManager);
 
         $this->mappingData += [
             'is_percent' => [
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/Fixture/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Core/Test/Fixture/ConfigData.xml
index 8bed37c9f9ba9a008e35327b901217acf596e00a..6b95f1c29ea9eac1be055d42985aeb2434aaecef 100644
--- a/dev/tests/functional/tests/app/Magento/Core/Test/Fixture/ConfigData.xml
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/Fixture/ConfigData.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="configData" 
            module="Magento_Core" 
            type="flat" 
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/Fixture/SystemVariable.xml b/dev/tests/functional/tests/app/Magento/Core/Test/Fixture/SystemVariable.xml
index 01f5710dc7a3d13d105d0dfbfadf6c06406d55f2..ccb72344e985faaeb96b30a64cf2faa43c8cc27d 100644
--- a/dev/tests/functional/tests/app/Magento/Core/Test/Fixture/SystemVariable.xml
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/Fixture/SystemVariable.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="systemVariable" 
            module="Magento_Core" 
            type="composite" 
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/Handler/ConfigData/Curl.php b/dev/tests/functional/tests/app/Magento/Core/Test/Handler/ConfigData/Curl.php
index 25be5b6e1ff02b819dc98d9fa7cc7467ce135eae..1a761f03046e6420cdef332767f73301ff55c0e5 100644
--- a/dev/tests/functional/tests/app/Magento/Core/Test/Handler/ConfigData/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/Handler/ConfigData/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\Core\Test\Handler\ConfigData;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
@@ -116,7 +115,8 @@ class Curl extends AbstractCurl implements ConfigDataInterface
         $curl->close();
 
         if (strpos($response, 'data-ui-id="messages-message-success"') === false) {
-            throw new \Exception("Settings are not applied! Response: $response");
+            $this->_eventManager->dispatchEvent(['curl_failed'], [$response]);
+            throw new \Exception("Configuration settings are not applied! Url: $url");
         }
     }
 
@@ -128,7 +128,6 @@ class Curl extends AbstractCurl implements ConfigDataInterface
      */
     protected function getUrl($section)
     {
-        return $_ENV['app_backend_url'] .
-        'admin/system_config/save/section/' . $section;
+        return $_ENV['app_backend_url'] . 'admin/system_config/save/section/' . $section;
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/Handler/SystemVariable/Curl.php b/dev/tests/functional/tests/app/Magento/Core/Test/Handler/SystemVariable/Curl.php
index 6c02a8ae428e78fb67e534d0d4b973f5d52417b9..0ded2518a3b8ff6f98febb4e8f24d851d007a664 100644
--- a/dev/tests/functional/tests/app/Magento/Core/Test/Handler/SystemVariable/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/Handler/SystemVariable/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\Core\Test\Handler\SystemVariable;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Fixture/CurrencySymbolEntity.xml b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Fixture/CurrencySymbolEntity.xml
index ad576cb9359802523e8db4a07f0c35d27626bf5f..9b37f90342b5b9e52c0a7b3fa232d85409f6c41f 100644
--- a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Fixture/CurrencySymbolEntity.xml
+++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Fixture/CurrencySymbolEntity.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="currencySymbolEntity" module="Magento_CurrencySymbol" type="flat" entity_type="core_config_data" repository_class="Magento\CurrencySymbol\Test\Repository\CurrencySymbolEntity" handler_interface="Magento\CurrencySymbol\Test\Handler\CurrencySymbolEntity\CurrencySymbolEntityInterface" class="Magento\CurrencySymbol\Test\Fixture\CurrencySymbolEntity">
     <dataset name="default">
         <field name="inherit_custom_currency_symbol" xsi:type="string">Yes</field>
diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Handler/CurrencySymbolEntity/Curl.php b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Handler/CurrencySymbolEntity/Curl.php
index d1b311772c5129904075f55be2f2137f21b0a3eb..34a5317bf187b7e1811371b985c8ecd962fa71b6 100644
--- a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Handler/CurrencySymbolEntity/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Handler/CurrencySymbolEntity/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\CurrencySymbol\Test\Handler\CurrencySymbolEntity;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Address.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Address.xml
index c092c7e6aa3102711ebab77769dc5a07d48f5c3e..09e93bbf76968ec5a9dc5cdcaec363c71607cb39 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Address.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Address.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="address" module="Magento_Customer" type="eav" entity_type="customer_address" collection="Magento\Customer\Model\Resource\Address\Collection" repository_class="Magento\Customer\Test\Repository\Address" handler_interface="Magento\Customer\Test\Handler\Address\AddressInterface" class="Magento\Customer\Test\Fixture\Address">
     <dataset name="default">
         <field name="firstname" xsi:type="string">John</field>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Customer.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Customer.xml
index d5afd5538951e8d4ecddcfaaeb6820c742ce3e04..fe4bdb7814a700b02ed39663d62dc2b11379f814 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Customer.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Customer.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="customer" module="Magento_Customer" type="eav" entity_type="customer" collection="Magento\Customer\Model\Resource\Customer\Collection" identifier="email" repository_class="Magento\Customer\Test\Repository\Customer" handler_interface="Magento\Customer\Test\Handler\Customer\CustomerInterface" class="Magento\Customer\Test\Fixture\Customer">
     <dataset name="default">
         <field name="firstname" xsi:type="string">John</field>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerGroupInjectable.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerGroupInjectable.xml
index b470b1c21b5e357d8532cecd566650cff0cb1a51..cec2cec3a74619acaa55ad468a50738441768df7 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerGroupInjectable.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerGroupInjectable.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="customerGroupInjectable" module="Magento_Customer" type="flat" entity_type="customer_group" collection="Magento\Customer\Model\Resource\Group\Collection" repository_class="Magento\Customer\Test\Repository\CustomerGroupInjectable" handler_interface="Magento\Customer\Test\Handler\CustomerGroupInjectable\CustomerGroupInjectableInterface" class="Magento\Customer\Test\Fixture\CustomerGroupInjectable">
     <dataset name="default">
         <field name="customer_group_code" xsi:type="string">customer_code_%isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Curl/CreateCustomerBackend.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Curl/CreateCustomerBackend.php
index e9860e68c44a4e346ab2a85c02021ae3c29992b2..cad3c992efa4681f8bf0851d50fa211c22aad7cc 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Curl/CreateCustomerBackend.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Curl/CreateCustomerBackend.php
@@ -8,7 +8,6 @@ namespace Magento\Customer\Test\Handler\Curl;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Curl/CreateCustomerGroup.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Curl/CreateCustomerGroup.php
index 22410354e5802ef983d6e3429696c464b086abf4..dadc4e66523bbc76d77a1ba8cbb52bba1fa744ff 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Curl/CreateCustomerGroup.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Curl/CreateCustomerGroup.php
@@ -8,7 +8,6 @@ namespace Magento\Customer\Test\Handler\Curl;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php
index 1831cdcbd2168ecca66ec836b256511705db838a..67d98b313afe2c576d620daed3c0dfd392d40315 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php
@@ -179,6 +179,7 @@ class Curl extends AbstractCurl implements CustomerInterface
         $curl->close();
 
         if (!strpos($response, 'data-ui-id="messages-message-success"')) {
+            $this->_eventManager->dispatchEvent(['curl_failed', [$response]]);
             throw new \Exception('Failed to update customer!');
         }
     }
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/CustomerGroupInjectable/Curl.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/CustomerGroupInjectable/Curl.php
index 4ca4adb67291be8c6fcaf88c6d694c73419a5a65..f2f7c1b52e6d809286919606322486f1421ee6bc 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/CustomerGroupInjectable/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/CustomerGroupInjectable/Curl.php
@@ -9,7 +9,6 @@ namespace Magento\Customer\Test\Handler\CustomerGroupInjectable;
 use Magento\Backend\Test\Handler\Extractor;
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Webapi/CreateCustomer.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Webapi/CreateCustomer.php
index 0087460d6e6f69ae0212096882fe0d40b5e06852..af06e68b03ef85b14d92d27f4044803de10e059b 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Webapi/CreateCustomer.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Webapi/CreateCustomer.php
@@ -24,7 +24,7 @@ class CreateCustomer extends Webapi
      */
     public function persist(FixtureInterface $fixture = null)
     {
-        $configuration = $this->_configuration->getParameter('handler/webapi');
+        $configuration = $this->_configuration->get('handler/0/webapi/0/value');
 
         $soap = new SoapTransport($configuration['soap']);
         return $soap->call('customerCustomerList', $fixture->getData());
diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Directory/Test/Repository/ConfigData.xml
index 546ccb6cda264b3d7100c471dd0489427a3d87cf..1afdae4142c3ca241c73666e9d8c9e310be9b530 100644
--- a/dev/tests/functional/tests/app/Magento/Directory/Test/Repository/ConfigData.xml
+++ b/dev/tests/functional/tests/app/Magento/Directory/Test/Repository/ConfigData.xml
@@ -9,27 +9,27 @@
     <repository class="Magento\Core\Test\Repository\ConfigData">
         <dataset name="config_currency_symbols_usd_and_uah">
             <field path="currency/options/allow" scope="currency" scope_id="1" xsi:type="array">
-                <item label="US Dollar" xsi:type="string">USD</item>
-                <item label="Ukrainian Hryvnia" xsi:type="string">UAH</item>
+                <item name="US Dollar" xsi:type="string">USD</item>
+                <item name="Ukrainian Hryvnia" xsi:type="string">UAH</item>
             </field>
         </dataset>
 
         <dataset name="config_currency_symbols_usd_and_uah_rollback">
             <field path="currency/options/allow" scope="currency" scope_id="1" xsi:type="array">
-                <item label="US Dollar" xsi:type="string">USD</item>
+                <item name="US Dollar" xsi:type="string">USD</item>
             </field>
         </dataset>
 
         <dataset name="config_currency_symbols_usd_and_chf">
             <field path="currency/options/allow" scope="currency" scope_id="1" xsi:type="array">
-                <item label="US Dollar" xsi:type="string">USD</item>
-                <item label="Swiss Franc" xsi:type="string">CHF</item>
+                <item name="US Dollar" xsi:type="string">USD</item>
+                <item name="Swiss Franc" xsi:type="string">CHF</item>
             </field>
         </dataset>
 
         <dataset name="config_currency_symbols_usd">
             <field path="currency/options/allow" scope="currency" scope_id="1" label="" xsi:type="array">
-                <item label="US Dollar" xsi:type="string">USD</item>
+                <item name="US Dollar" xsi:type="string">USD</item>
             </field>
         </dataset>
     </repository>
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/DownloadableProduct.xml b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/DownloadableProduct.xml
index 572574f962f25db2eff34e2a52855ec760a87e7a..7c7caf2f5c2495c7e0fdf71340026c83ad3e7bb3 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/DownloadableProduct.xml
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/DownloadableProduct.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="downloadableProduct" module="Magento_Downloadable" type="eav" entity_type="catalog_product" product_type="downloadable" collection="Magento\Catalog\Model\Resource\Product\Collection" identifier="sku" repository_class="Magento\Downloadable\Test\Repository\DownloadableProduct" handler_interface="Magento\Downloadable\Test\Handler\DownloadableProduct\DownloadableProductInterface" class="Magento\Downloadable\Test\Fixture\DownloadableProduct">
     <dataset name="default">
         <field name="name" xsi:type="string">DownloadableProduct_%isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Handler/DownloadableProduct/Curl.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Handler/DownloadableProduct/Curl.php
index 9812c5b6aca7e4266eebc0c6e8a99c5ac2c64155..7d05456656c3ccb3c46190a06b19c26c6cd02950 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Handler/DownloadableProduct/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Handler/DownloadableProduct/Curl.php
@@ -8,7 +8,8 @@ namespace Magento\Downloadable\Test\Handler\DownloadableProduct;
 
 use Magento\Catalog\Test\Handler\CatalogProductSimple\Curl as ProductCurl;
 use Magento\Mtf\Fixture\FixtureInterface;
-use Magento\Mtf\Config;
+use Magento\Mtf\Config\DataInterface;
+use Magento\Mtf\System\Event\EventManagerInterface;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
@@ -22,11 +23,12 @@ class Curl extends ProductCurl implements DownloadableProductInterface
     /**
      * Constructor
      *
-     * @param Config $configuration
+     * @param DataInterface $configuration
+     * @param EventManagerInterface $eventManager
      */
-    public function __construct(Config $configuration)
+    public function __construct(DataInterface $configuration, EventManagerInterface $eventManager)
     {
-        parent::__construct($configuration);
+        parent::__construct($configuration, $eventManager);
 
         $this->mappingData += [
             'links_purchased_separately' => [
diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Fixture/GiftMessage.xml b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Fixture/GiftMessage.xml
index be06e0300b46846747b71fd0a6b99c1d621277a3..d11995d1e7dc6baef8dc65be2371f688ec1c73dc 100644
--- a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Fixture/GiftMessage.xml
+++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/Fixture/GiftMessage.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="giftMessage" module="Magento_GiftMessage" type="flat" entity_type="gift_message" collection="Magento\GiftMessage\Model\Resource\Message\Collection" identifier="gift_message_id" repository_class="Magento\GiftMessage\Test\Repository\GiftMessage" class="Magento\GiftMessage\Test\Fixture\GiftMessage">
     <dataset name="default">
         <field name="allow_gift_options" xsi:type="string">Yes</field>
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Fixture/GoogleShoppingAttribute.xml b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Fixture/GoogleShoppingAttribute.xml
index 61944b24eed8fafc0154028a32cd80db5d596d75..b33b9b5cc9eb62b3c8ae87cebeb824634d22db03 100644
--- a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Fixture/GoogleShoppingAttribute.xml
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Fixture/GoogleShoppingAttribute.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="googleShoppingAttribute" module="Magento_GoogleShopping" type="flat" entity_type="googleshopping_types" collection="Magento\GoogleShopping\Model\Resource\Attribute\Collection" repository_class="Magento\GoogleShopping\Test\Repository\GoogleShoppingAttribute" handler_interface="Magento\GoogleShopping\Test\Handler\GoogleShoppingAttribute\GoogleShoppingAttributeInterface" class="Magento\GoogleShopping\Test\Fixture\GoogleShoppingAttribute">
     <dataset name="default">
         <field name="target_country" xsi:type="string">United States</field>
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/GroupedProduct.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/GroupedProduct.xml
index 22c825f3680670eb388bd767c7f79efbdf545bcf..5fc47bd6a0c653287b86c7ccc4ecd29838839f8d 100644
--- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/GroupedProduct.xml
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/GroupedProduct.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="groupedProduct" module="Magento_GroupedProduct" type="eav" entity_type="catalog_product" product_type="grouped" collection="Magento\Catalog\Model\Resource\Product\Collection" identifier="sku" repository_class="Magento\GroupedProduct\Test\Repository\GroupedProduct" handler_interface="Magento\GroupedProduct\Test\Handler\GroupedProduct\GroupedProductInterface" class="Magento\GroupedProduct\Test\Fixture\GroupedProduct">
     <dataset name="default">
         <field name="name" xsi:type="string">GroupedProduct_%isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/ImportExport/Test/Fixture/ImportExport.xml b/dev/tests/functional/tests/app/Magento/ImportExport/Test/Fixture/ImportExport.xml
index 08b3dd3c556210d2efd6bc3a25a85e048a209413..01f5463b5f052fac98c49d795f3ac38e4979139f 100644
--- a/dev/tests/functional/tests/app/Magento/ImportExport/Test/Fixture/ImportExport.xml
+++ b/dev/tests/functional/tests/app/Magento/ImportExport/Test/Fixture/ImportExport.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="importExport" module="Magento_ImportExport" type="flat" entity_type="importexport_importdata" class="Magento\ImportExport\Test\Fixture\ImportExport">
     <dataset name="default">
         <field name="entity" xsi:type="string">Products</field>
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertSuccessInstall.php b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertSuccessInstall.php
index 7bf6181d89616a2c86b5b08b108f19e4c6086aa6..2f7039d86953e8694ebe824973be8225edac004c 100644
--- a/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertSuccessInstall.php
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertSuccessInstall.php
@@ -52,6 +52,11 @@ class AssertSuccessInstall extends AbstractConstraint
         $dbData = $installPage->getInstallBlock()->getDbInfo();
 
         $allData = array_merge($user->getData(), $installConfig->getData());
+
+        foreach ($installConfig->getData() as $key => $value) {
+            $allData[$key] = isset($value['value']) ? $value['value'] : $value;
+        }
+
         $allData['admin'] = $allData['web'] . $allData['admin'] . '/';
 
         foreach ($this->adminFieldsList as $field) {
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Fixture/Install.xml b/dev/tests/functional/tests/app/Magento/Install/Test/Fixture/Install.xml
index f2d6025c12beb22e083405f5592bf2a209e53985..d846de8f0bd45b0ed71068f8146e171994d682f6 100644
--- a/dev/tests/functional/tests/app/Magento/Install/Test/Fixture/Install.xml
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Fixture/Install.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="install" module="Magento_Install" type="virtual" entity_type="install" repository_class="Magento\Install\Test\Repository\Install" handler_interface="Magento\Install\Test\Handler\Install\InstallInterface" class="Magento\Install\Test\Fixture\Install">
     <field name="dbHost"/>
     <field name="dbUser"/>
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest.php b/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest.php
index 96e18ffc8452ce74121d887ac3290f17842f1277..74ec107e09a60690f1292e847fbc0a5c289f41b0 100644
--- a/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest.php
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest.php
@@ -10,10 +10,9 @@ use Magento\Cms\Test\Page\CmsIndex;
 use Magento\Install\Test\Page\Install;
 use Magento\Install\Test\Fixture\Install as InstallConfig;
 use Magento\User\Test\Fixture\User;
-use Magento\Mtf\Config;
 use Magento\Mtf\Fixture\FixtureFactory;
 use Magento\Mtf\TestCase\Injectable;
-use Magento\Mtf\Config\GlobalConfig;
+use Magento\Mtf\Config\DataInterface;
 use Magento\Install\Test\Constraint\AssertAgreementTextPresent;
 use Magento\Install\Test\Constraint\AssertSuccessfulReadinessCheck;
 use Magento\Mtf\ObjectManagerFactory;
@@ -68,14 +67,14 @@ class InstallTest extends Injectable
      */
     public function __prepare()
     {
-        $config = ObjectManagerFactory::getObjectManager()->get('Magento\Mtf\Config\GlobalConfig');
+        $config = ObjectManagerFactory::getObjectManager()->get('Magento\Mtf\Config\DataInterface');
         // Prepare config data
-        $configData['dbHost'] = $config->get('install/host');
-        $configData['dbUser'] = $config->get('install/user');
-        $configData['dbPassword'] = $config->get('install/password');
-        $configData['dbName'] = $config->get('install/dbName');
-        $configData['web'] = $config->get('install/baseUrl');
-        $configData['admin'] = $config->get('install/backendName');
+        $configData['dbHost'] = $config->get('install/0/host/0');
+        $configData['dbUser'] = $config->get('install/0/user/0');
+        $configData['dbPassword'] = $config->get('install/0/password/0');
+        $configData['dbName'] = $config->get('install/0/dbName/0');
+        $configData['web'] = $config->get('install/0/baseUrl/0');
+        $configData['admin'] = $config->get('install/0/backendName/0');
 
         return ['configData' => $configData];
     }
diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Fixture/Integration.xml b/dev/tests/functional/tests/app/Magento/Integration/Test/Fixture/Integration.xml
index 3e58557ff604b5282f1e552fd95d3f0ad6bf65de..30c8310ea5534bdabf634e3e4e005c1ac71a87ca 100644
--- a/dev/tests/functional/tests/app/Magento/Integration/Test/Fixture/Integration.xml
+++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Fixture/Integration.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="integration" module="Magento_Integration" type="composite" entity_type="integration" collection="Magento\Integration\Model\Resource\Integration\Collection" repository_class="Magento\Integration\Test\Repository\Integration" handler_interface="Magento\Integration\Test\Handler\Integration\IntegrationInterface" class="Magento\Integration\Test\Fixture\Integration">
     <dataset name="default">
         <field name="name" xsi:type="string">default_integration_%isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Handler/Integration/Curl.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Handler/Integration/Curl.php
index d8047148bec4461e4396776c0cb3a1b2d5621957..900572434e6de4e5719fabe54f620e87053ce375 100644
--- a/dev/tests/functional/tests/app/Magento/Integration/Test/Handler/Integration/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Handler/Integration/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\Integration\Test\Handler\Integration;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Newsletter/Test/Fixture/Template.xml b/dev/tests/functional/tests/app/Magento/Newsletter/Test/Fixture/Template.xml
index 9d216c522278f6d9ac793770a231c61ed446e108..6311e64c6602a507e3da61125c06670429df3af5 100644
--- a/dev/tests/functional/tests/app/Magento/Newsletter/Test/Fixture/Template.xml
+++ b/dev/tests/functional/tests/app/Magento/Newsletter/Test/Fixture/Template.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="template" module="Magento_Newsletter" type="flat" entity_type="newsletter_template" collection="Magento\Newsletter\Model\Resource\Template\Collection" identifier="template_id" repository_class="Magento\Newsletter\Test\Repository\Template" handler_interface="Magento\Newsletter\Test\Handler\Template\TemplateInterface" class="Magento\Newsletter\Test\Fixture\Template">
     <dataset name="default">
         <field name="code" xsi:type="string">TemplateName%isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/Newsletter/Test/Handler/Template/Curl.php b/dev/tests/functional/tests/app/Magento/Newsletter/Test/Handler/Template/Curl.php
index 7578ea44254810996850a51e69d5b37d0377670b..8d94f60cda0c41ae9a9c18434edb8780d9165db6 100644
--- a/dev/tests/functional/tests/app/Magento/Newsletter/Test/Handler/Template/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Newsletter/Test/Handler/Template/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\Newsletter\Test\Handler\Template;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/OfflinePayments/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/OfflinePayments/Test/Repository/ConfigData.xml
index 0e2819446d17c536bc36b2f20dc6444b5f102429..a6eb9d9e85ee49354c799e5b7d254786b5198c5c 100644
--- a/dev/tests/functional/tests/app/Magento/OfflinePayments/Test/Repository/ConfigData.xml
+++ b/dev/tests/functional/tests/app/Magento/OfflinePayments/Test/Repository/ConfigData.xml
@@ -19,7 +19,7 @@
             <field path="payment/cashondelivery/active" scope="payment" scope_id="1" label="Yes" xsi:type="string">1</field>
             <field path="payment/cashondelivery/allowspecific" scope="payment" scope_id="1" label="Specific Countries" xsi:type="string">1</field>
             <field path="payment/cashondelivery/specificcountry" scope="payment" scope_id="1" xsi:type="array">
-                <item label="United Kingdom" xsi:type="string">GB</item>
+                <item name="United Kingdom" xsi:type="string">GB</item>
             </field>
         </dataset>
 
@@ -40,7 +40,7 @@
             <field path="payment/checkmo/active" scope="payment" scope_id="1" label="Yes" xsi:type="string">1</field>
             <field path="payment/checkmo/allowspecific" scope="payment" scope_id="1" label="Specific Countries" xsi:type="string">1</field>
             <field path="payment/checkmo/specificcountry" scope="payment" scope_id="1" xsi:type="array">
-                <item label="United Kingdom" xsi:type="string">GB</item>
+                <item name="United Kingdom" xsi:type="string">GB</item>
             </field>
         </dataset>
 
@@ -61,7 +61,7 @@
             <field path="payment/banktransfer/active" scope="payment" scope_id="1" label="Yes" xsi:type="string">1</field>
             <field path="payment/banktransfer/allowspecific" scope="payment" scope_id="1" label="Specific Countries" xsi:type="string">1</field>
             <field path="payment/banktransfer/specificcountry" scope="payment" scope_id="1" xsi:type="array">
-                <item label="United Kingdom" xsi:type="string">GB</item>
+                <item name="United Kingdom" xsi:type="string">GB</item>
             </field>
         </dataset>
 
@@ -82,7 +82,7 @@
             <field path="payment/purchaseorder/active" scope="payment" scope_id="1" label="Yes" xsi:type="string">1</field>
             <field path="payment/purchaseorder/allowspecific" scope="payment" scope_id="1" label="Specific Countries" xsi:type="string">1</field>
             <field path="payment/purchaseorder/specificcountry" scope="payment" scope_id="1" xsi:type="array">
-                <item label="United Kingdom" xsi:type="string">GB</item>
+                <item name="United Kingdom" xsi:type="string">GB</item>
             </field>
         </dataset>
 
diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Fixture/Rating.xml b/dev/tests/functional/tests/app/Magento/Review/Test/Fixture/Rating.xml
index 99e16141dcdfc1ce45c3b9c890d6aac75a1e05ab..d551947d8c420dd84ac3396c240ec9bf0d140a76 100755
--- a/dev/tests/functional/tests/app/Magento/Review/Test/Fixture/Rating.xml
+++ b/dev/tests/functional/tests/app/Magento/Review/Test/Fixture/Rating.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="rating" module="Magento_Review" type="flat" entity_type="rating" collection="Magento\Review\Model\Resource\Rating\Collection" identifier="rating_code" repository_class="Magento\Review\Test\Repository\Rating" handler_interface="Magento\Review\Test\Handler\Rating\RatingInterface" class="Magento\Review\Test\Fixture\Rating">
     <dataset name="default">
         <field name="rating_code" xsi:type="string">Rating %isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Fixture/Review.xml b/dev/tests/functional/tests/app/Magento/Review/Test/Fixture/Review.xml
index 50ede32fea8d7b74f06a6395941376ef155ef70f..a118552b4f5c6c97ee8523795f77d6e8b4d79d5b 100755
--- a/dev/tests/functional/tests/app/Magento/Review/Test/Fixture/Review.xml
+++ b/dev/tests/functional/tests/app/Magento/Review/Test/Fixture/Review.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="review" module="Magento_Review" type="composite" collection="Magento\Review\Model\Resource\Review\Collection" repository_class="Magento\Review\Test\Repository\Review" handler_interface="Magento\Review\Test\Handler\Review\ReviewInterface" class="Magento\Review\Test\Fixture\Review">
     <dataset name="default">
         <field name="status_id" xsi:type="string">Approved</field>
diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Handler/Rating/Curl.php b/dev/tests/functional/tests/app/Magento/Review/Test/Handler/Rating/Curl.php
index 58206282eb611641755d1f42f2e8c4667a1e4a97..ea7b1d6bad431f6814c07c6c5d97c553071dfe71 100755
--- a/dev/tests/functional/tests/app/Magento/Review/Test/Handler/Rating/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Review/Test/Handler/Rating/Curl.php
@@ -9,7 +9,6 @@ namespace Magento\Review\Test\Handler\Rating;
 use Magento\Backend\Test\Handler\Extractor;
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Handler/Review/Curl.php b/dev/tests/functional/tests/app/Magento/Review/Test/Handler/Review/Curl.php
index df3c3004b7c979c7a2f84efc3588c373ad89038d..986d1f4883123d27e8f743e5473346c9948f9399 100644
--- a/dev/tests/functional/tests/app/Magento/Review/Test/Handler/Review/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Review/Test/Handler/Review/Curl.php
@@ -6,7 +6,6 @@
 
 namespace Magento\Review\Test\Handler\Review;
 
-use Magento\Mtf\Config;
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
diff --git a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Fixture/Sitemap.xml b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Fixture/Sitemap.xml
index dc51c43e5dd1f27e7789fbe1da1972a324120885..6927691a7aa8e27bc0be0ff11dd70d694724a917 100644
--- a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Fixture/Sitemap.xml
+++ b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Fixture/Sitemap.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="sitemap" module="Magento_Sitemap" type="flat" entity_type="sitemap" collection="Magento\Sitemap\Model\Resource\Sitemap\Collection" repository_class="Magento\Sitemap\Test\Repository\Sitemap" handler_interface="Magento\Sitemap\Test\Handler\Sitemap\SitemapInterface" class="Magento\Sitemap\Test\Fixture\Sitemap">
     <dataset name="default">
         <field name="sitemap_filename" xsi:type="string">sitemap.xml</field>
diff --git a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Handler/Sitemap/Curl.php b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Handler/Sitemap/Curl.php
index c8b09124666bd8ab70c40b40bdf1f93affca8550..e78e858ded474e8669a7dc19f81afd22fe245ee8 100644
--- a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Handler/Sitemap/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Handler/Sitemap/Curl.php
@@ -10,7 +10,6 @@ use Magento\Backend\Test\Handler\Extractor;
 use Magento\Sitemap\Test\Handler\Sitemap;
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Store.xml b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Store.xml
index b9be593561d7c588beb8de9f6aff896b262a5270..3a95b594d8400494d3809ae19d53599b063821f8 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Store.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Store.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="store" module="Magento_Store" type="flat" entity_type="store" collection="Magento\Store\Model\Resource\Store\Collection" repository_class="Magento\Store\Test\Repository\Store" handler_interface="Magento\Store\Test\Handler\Store\StoreInterface" class="Magento\Store\Test\Fixture\Store">
     <dataset name="default">
         <field name="group_id" xsi:type="array">
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/StoreGroup.xml b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/StoreGroup.xml
index fcd43ace417f90fc83a88a6d89d96a3eb24db03f..7b6a5ad692b1add59ad8803aa85e8832e8b6db9a 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/StoreGroup.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/StoreGroup.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="storeGroup" module="Magento_Store" type="flat" entity_type="store_group" collection="Magento\Store\Model\Resource\Group\Collection" identifier="" repository_class="Magento\Store\Test\Repository\StoreGroup" handler_interface="Magento\Store\Test\Handler\StoreGroup\StoreGroupInterface" class="Magento\Store\Test\Fixture\StoreGroup">
     <dataset name="default">
         <field name="website_id" xsi:type="array">
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Website.xml b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Website.xml
index 261b506e96a6127b5de859597b3ca13bd6d717ef..0878f90e302a1d1594eac5f1d8af895f8fd4e418 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Website.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Website.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="website" module="Magento_Store" type="flat" entity_type="store_website" collection="Magento\Store\Model\Resource\Website\Collection" identifier="code" repository_class="Magento\Store\Test\Repository\Website" handler_interface="Magento\Store\Test\Handler\Website\WebsiteInterface" class="Magento\Store\Test\Fixture\Website">
     <dataset name="default">
         <field name="name" xsi:type="string">Main Website</field>
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Store/Curl.php b/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Store/Curl.php
index aaa0e84ce103a1a2813086a88aca122f793eddb1..d6293b08cd50a9f0773b6bf4b9c8680033b36553 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Store/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Store/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\Store\Test\Handler\Store;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Handler/StoreGroup/Curl.php b/dev/tests/functional/tests/app/Magento/Store/Test/Handler/StoreGroup/Curl.php
index 9922064088af8416f8e7d3adde471a174448a789..71faf510eed5e5886c59a8a19398f28cad987ed5 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Handler/StoreGroup/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Handler/StoreGroup/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\Store\Test\Handler\StoreGroup;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Website/Curl.php b/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Website/Curl.php
index 4de491270189098448ffb31ad31bfb2a87a4485b..bbd183601e4ef3697021b64745bad2b0bdadb64f 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Website/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Website/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\Store\Test\Handler\Website;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxClass.xml b/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxClass.xml
index 13e6c00c52879193a38fb344bba0ccf716eab9b1..30710bb5b2f81fc5e2f5f53025b9f6d5dc225476 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxClass.xml
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxClass.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="taxClass" module="Magento_Tax" type="flat" entity_type="tax_class" collection="Magento\Tax\Model\Resource\TaxClass\Collection" identifier="" repository_class="Magento\Tax\Test\Repository\TaxClass" handler_interface="Magento\Tax\Test\Handler\TaxClass\TaxClassInterface" class="Magento\Tax\Test\Fixture\TaxClass">
     <dataset name="default">
         <field name="class_name" xsi:type="string">Tax Class %isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRate.xml b/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRate.xml
index a344ad905106d0f0b6b363d9fc83fabb103d0779..b9a4a30142690008bd8b142c8e8a74692b19307a 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRate.xml
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRate.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="taxRate" module="Magento_Tax" type="flat" entity_type="tax_calculation_rate" collection="Magento\Tax\Model\Resource\Calculation\Rate\Collection" identifier="code" repository_class="Magento\Tax\Test\Repository\TaxRate" handler_interface="Magento\Tax\Test\Handler\TaxRate\TaxRateInterface" class="Magento\Tax\Test\Fixture\TaxRate">
     <dataset name="default">
         <field name="code" xsi:type="string">Tax Rate %isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRule.xml b/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRule.xml
index 82d0dc07793aeef0b07f4e2186b8bdb19830b146..b53f3f1eba5d9b4c3f29653c282cf1b7af82820a 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRule.xml
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRule.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="taxRule" module="Magento_Tax" type="flat" entity_type="tax_calculation_rule" collection="Magento\Tax\Model\Resource\Calculation\Rule\Collection" identifier="code" repository_class="Magento\Tax\Test\Repository\TaxRule" handler_interface="Magento\Tax\Test\Handler\TaxRule\TaxRuleInterface" class="Magento\Tax\Test\Fixture\TaxRule">
     <dataset name="default">
         <field name="code" xsi:type="string">TaxIdentifier%isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxClass/Curl.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxClass/Curl.php
index 28e77379db72e1010f28e6bf0212e34ac8a2feea..b6d6072bcb5a13ebcaba872d5465f00ed29681e8 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxClass/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxClass/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\Tax\Test\Handler\TaxClass;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRate/Curl.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRate/Curl.php
index 6cc269c5525d86bd6d4d7b854a4a3231d4dd8fbf..e1b370a6e44f8463404f512142f91449412b9903 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRate/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRate/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\Tax\Test\Handler\TaxRate;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRule/Curl.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRule/Curl.php
index 2d47e8b3bdb62090385ef7b15d2bbff156bbc80f..872f49ae0387a92bd9bd19ad7a6b0ccbdfe6ee0b 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRule/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRule/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\Tax\Test\Handler\TaxRule;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/Ups/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Ups/Test/Repository/ConfigData.xml
index a6d197824433ed7cae1e7ede9e230d4b6defe362..6c8afa0db50de401e34b56f1bd04c938e74a9016 100644
--- a/dev/tests/functional/tests/app/Magento/Ups/Test/Repository/ConfigData.xml
+++ b/dev/tests/functional/tests/app/Magento/Ups/Test/Repository/ConfigData.xml
@@ -29,17 +29,17 @@
             <field path="carriers/ups/tracking_xml_url" scope="carriers" scope_id="1" label="" xsi:type="string">https://wwwcie.ups.com/ups.app/xml/Track</field>
             <field path="carriers/ups/unit_of_measure" scope="carriers" scope_id="1" label="LBS" xsi:type="string">LBS</field>
             <field path="carriers/ups/allowed_methods" scope="carriers" scope_id="1" xsi:type="array">
-                <item label="UPS Standard" xsi:type="string">11</item>
-                <item label="UPS Three-Day Select" xsi:type="string">12</item>
-                <item label="UPS Next Day Air Early A.M." xsi:type="string">14</item>
-                <item label="UPS Worldwide Express Plus" xsi:type="string">54</item>
-                <item label="UPS Second Day Air A.M." xsi:type="string">59</item>
-                <item label="UPS Worldwide Saver" xsi:type="string">65</item>
-                <item label="UPS Next Day Air" xsi:type="string">01</item>
-                <item label="UPS Second Day Air" xsi:type="string">02</item>
-                <item label="UPS Ground" xsi:type="string">03</item>
-                <item label="UPS Worldwide Express" xsi:type="string">07</item>
-                <item label="UPS Worldwide Expedited" xsi:type="string">08</item>
+                <item name="UPS Standard" xsi:type="string">11</item>
+                <item name="UPS Three-Day Select" xsi:type="string">12</item>
+                <item name="UPS Next Day Air Early A.M." xsi:type="string">14</item>
+                <item name="UPS Worldwide Express Plus" xsi:type="string">54</item>
+                <item name="UPS Second Day Air A.M." xsi:type="string">59</item>
+                <item name="UPS Worldwide Saver" xsi:type="string">65</item>
+                <item name="UPS Next Day Air" xsi:type="string">01</item>
+                <item name="UPS Second Day Air" xsi:type="string">02</item>
+                <item name="UPS Ground" xsi:type="string">03</item>
+                <item name="UPS Worldwide Express" xsi:type="string">07</item>
+                <item name="UPS Worldwide Expedited" xsi:type="string">08</item>
             </field>
             <field path="carriers/ups/sallowspecific" scope="carriers" scope_id="1" label="All Allowed Countries" xsi:type="string">0</field>
             <field path="carriers/ups/showmethod" scope="carriers" scope_id="1" label="No" xsi:type="string">0</field>
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.xml
index a73037a6417cea31f404c94f66c3f1fd72b0a6af..f0fda4e5442de3338d518ecad3cc758bfa82f5db 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.xml
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="urlRewrite" module="Magento_UrlRewrite" type="virtual" entity_type="url_rewrite" collection="Magento\UrlRewrite\Model\Resource\UrlRewriteCollection" identifier="request_path" repository_class="Magento\UrlRewrite\Test\Repository\UrlRewrite" handler_interface="Magento\UrlRewrite\Test\Handler\UrlRewrite\UrlRewriteInterface" class="Magento\UrlRewrite\Test\Fixture\UrlRewrite">
     <dataset name="default">
         <field name="store_id" xsi:type="string">Main Website/Main Website Store/Default Store View</field>
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/Curl.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/Curl.php
index ccc680aab72bdac4600300aaf370b56e22e1bc66..ab9aaa6a50f976b8b03880fb2a6c9bb6d25c4db1 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/Curl.php
@@ -8,7 +8,6 @@ namespace Magento\UrlRewrite\Test\Handler\UrlRewrite;
 
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Fixture/Role.xml b/dev/tests/functional/tests/app/Magento/User/Test/Fixture/Role.xml
index 671556ced60023e557fce39be0f51dd6fef2d5d9..39ac5778e0cc30e30d6d8edeca2824949954327d 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/Fixture/Role.xml
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Fixture/Role.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
     <fixture name="role" module="Magento_User" type="flat" entity_type="authorization_role" collection="Magento\User\Model\Resource\Role\User\Collection" repository_class="Magento\User\Test\Repository\Role" handler_interface="Magento\User\Test\Handler\Role\RoleInterface" class="Magento\User\Test\Fixture\Role">
         <dataset name="default">
             <field name="rolename" xsi:type="string">AdminRole%isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Fixture/User.xml b/dev/tests/functional/tests/app/Magento/User/Test/Fixture/User.xml
index 1044838fb45f6ee3a9bb9f0467e8425451130790..80c969cf4bbfe3c393e25e8abae8066e552ec028 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/Fixture/User.xml
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Fixture/User.xml
@@ -5,7 +5,7 @@
  * See COPYING.txt for license details.
  */
  -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
   <fixture name="user" module="Magento_User" type="flat" entity_type="admin_user" collection="Magento\User\Model\Resource\User\Collection" repository_class="Magento\User\Test\Repository\User" handler_interface="Magento\User\Test\Handler\User\UserInterface" class="Magento\User\Test\Fixture\User">
     <dataset name="default">
         <field name="username" xsi:type="string">AdminUser%isolation%</field>
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Fixture/User/CurrentPassword.php b/dev/tests/functional/tests/app/Magento/User/Test/Fixture/User/CurrentPassword.php
index 31ab14a90355b4a9ed4f4cf01dcc246adc61c417..7c7e8bc1d8a073e2c3c848ab0390e2e97232af14 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/Fixture/User/CurrentPassword.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Fixture/User/CurrentPassword.php
@@ -36,10 +36,10 @@ class CurrentPassword implements FixtureInterface
     public function __construct(array $params, $data = '')
     {
         $this->params = $params;
-        /** @var \Magento\Mtf\Config $systemConfig */
+        /** @var \Magento\Mtf\Config\DataInterface $systemConfig */
         if ($data == '%current_password%') {
-            $systemConfig = ObjectManager::getInstance()->create('Magento\Mtf\Config');
-            $data = $systemConfig->getParameter('application/backendPassword');
+            $systemConfig = ObjectManager::getInstance()->create('Magento\Mtf\Config\DataInterface');
+            $data = $systemConfig->get('application/0/backendPassword/0/value');
         }
         $this->data = $data;
     }
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Handler/Role/Curl.php b/dev/tests/functional/tests/app/Magento/User/Test/Handler/Role/Curl.php
index 3e8fa860192b79b6a8e37b7a38c8b15a46826333..3f482454ac0a1fe4383ecb365ac155899add15cb 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/Handler/Role/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Handler/Role/Curl.php
@@ -9,7 +9,8 @@ namespace Magento\User\Test\Handler\Role;
 use Magento\Backend\Test\Handler\Extractor;
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
+use Magento\Mtf\Config\DataInterface;
+use Magento\Mtf\System\Event\EventManagerInterface;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
@@ -28,15 +29,16 @@ class Curl extends AbstractCurl implements RoleInterface
 
     /**
      * @constructor
-     * @param Config $configuration
+     * @param DataInterface $configuration
+     * @param EventManagerInterface $eventManager
      */
-    public function __construct(Config $configuration)
+    public function __construct(DataInterface $configuration, EventManagerInterface $eventManager)
     {
         $this->mappingData = array_merge(
             (null !== $this->mappingData) ? $this->mappingData : [],
             $this->additionalMappingData
         );
-        parent::__construct($configuration);
+        parent::__construct($configuration, $eventManager);
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Handler/User/Curl.php b/dev/tests/functional/tests/app/Magento/User/Test/Handler/User/Curl.php
index 1026e872f89221e111761229063be05f2bf2e24e..a1b5ea977ca197f908052e708db8a0619e796f2f 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/Handler/User/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Handler/User/Curl.php
@@ -9,7 +9,6 @@ namespace Magento\User\Test\Handler\User;
 use Magento\Backend\Test\Handler\Extractor;
 use Magento\Mtf\Fixture\FixtureInterface;
 use Magento\Mtf\Handler\Curl as AbstractCurl;
-use Magento\Mtf\Config;
 use Magento\Mtf\Util\Protocol\CurlInterface;
 use Magento\Mtf\Util\Protocol\CurlTransport;
 use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
diff --git a/dev/tests/integration/testsuite/Magento/Multishipping/Controller/CheckoutTest.php b/dev/tests/integration/testsuite/Magento/Multishipping/Controller/CheckoutTest.php
index c70148b0ffcdf0a06f2076da845c4d17349ac51f..30d0ee18b96e64b214d3819cd7e58fb6f3dbb940 100644
--- a/dev/tests/integration/testsuite/Magento/Multishipping/Controller/CheckoutTest.php
+++ b/dev/tests/integration/testsuite/Magento/Multishipping/Controller/CheckoutTest.php
@@ -5,51 +5,67 @@
  */
 namespace Magento\Multishipping\Controller;
 
-use Magento\TestFramework\Helper\Bootstrap;
+use \Magento\Multishipping\Model\Checkout\Type\Multishipping\State;
 
 /**
  * Test class for \Magento\Multishipping\Controller\Checkout
  *
  * @magentoAppArea frontend
+ * @magentoDataFixture Magento/Sales/_files/quote.php
+ * @magentoDataFixture Magento/Customer/_files/customer.php
  */
 class CheckoutTest extends \Magento\TestFramework\TestCase\AbstractController
 {
     /**
-     * Covers app/code/Magento/Checkout/Block/Multishipping/Payment/Info.php
-     * and app/code/Magento/Checkout/Block/Multishipping/Overview.php
+     * @var \Magento\Quote\Model\Quote
+     */
+    protected $quote;
+
+    /**
+     * @var \Magento\Checkout\Model\Session
+     */
+    protected $checkoutSession;
+
+    /**
+     * @inheritdoc
+     */
+    public function setUp()
+    {
+        parent::setUp();
+        $this->quote = $this->_objectManager->create('Magento\Quote\Model\Quote');
+        $this->checkoutSession = $this->_objectManager->get('Magento\Checkout\Model\Session');
+
+        $this->quote->load('test01', 'reserved_order_id');
+        $this->checkoutSession->setQuoteId($this->quote->getId());
+        $this->checkoutSession->setCartWasUpdated(false);
+    }
+
+    /**
+     * Covers \Magento\Multishipping\Block\Checkout\Payment\Info and \Magento\Multishipping\Block\Checkout\Overview
      *
-     * @magentoDataFixture Magento/Sales/_files/quote.php
-     * @magentoDataFixture Magento/Customer/_files/customer.php
      * @magentoConfigFixture current_store multishipping/options/checkout_multiple 1
      */
     public function testOverviewAction()
     {
-        /** @var $quote \Magento\Quote\Model\Quote */
-        $quote = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Quote\Model\Quote');
-        $quote->load('test01', 'reserved_order_id');
-
-        \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Checkout\Model\Session')
-            ->setQuoteId($quote->getId());
-
+        /** @var \Magento\Framework\Data\Form\FormKey $formKey */
         $formKey = $this->_objectManager->get('Magento\Framework\Data\Form\FormKey');
         $logger = $this->getMock('Psr\Log\LoggerInterface', [], [], '', false);
-
-        /** @var $session \Magento\Customer\Model\Session */
-        $session = Bootstrap::getObjectManager()->create('Magento\Customer\Model\Session', [$logger]);
-
-        /** @var \Magento\Customer\Api\AccountManagementInterface  $service */
-        $service = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
-            ->create('Magento\Customer\Api\AccountManagementInterface');
+        /** @var \Magento\Customer\Api\AccountManagementInterface $service */
+        $service = $this->_objectManager->create('Magento\Customer\Api\AccountManagementInterface');
         $customer = $service->authenticate('customer@example.com', 'password');
+        /** @var \Magento\Customer\Model\Session $customerSession */
+        $customerSession = $this->_objectManager->create('Magento\Customer\Model\Session', [$logger]);
+        $customerSession->setCustomerDataAsLoggedIn($customer);
+        $this->checkoutSession->setCheckoutState(State::STEP_BILLING);
 
-        $session->setCustomerDataAsLoggedIn($customer);
         $this->getRequest()->setPostValue('payment', ['method' => 'checkmo']);
         $this->dispatch('multishipping/checkout/overview');
         $html = $this->getResponse()->getBody();
+
         $this->assertContains('<div class="box box-billing-method">', $html);
         $this->assertContains('<div class="box box-shipping-method">', $html);
         $this->assertContains(
-            '<dt class="title">' . $quote->getPayment()->getMethodInstance()->getTitle() . '</dt>',
+            '<dt class="title">' . $this->quote->getPayment()->getMethodInstance()->getTitle() . '</dt>',
             $html
         );
         $this->assertContains('<span class="price">$10.00</span>', $html);
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/HhvmCompatibilityTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/HhvmCompatibilityTest.php
index c3a9fe9933ee4948c40bbd5630eea75f0b46a1e0..b7c342c1fd4ecdc410a7558a1a3131d76193c125 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/HhvmCompatibilityTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/HhvmCompatibilityTest.php
@@ -36,6 +36,7 @@ class HhvmCompatibilityTest extends \PHPUnit_Framework_TestCase
         'mime_magic.magicfile',
         'display_errors',
         'default_socket_timeout',
+        'pcre.recursion_limit',
     ];
 
     public function testAllowedIniGetSetDirectives()
diff --git a/dev/tools/performance-toolkit/benchmark.jmx b/dev/tools/performance-toolkit/benchmark.jmx
index 1fe4919a59eb43c0f72910d7de13a1448d2b8ab8..7d3d7aef7fa0ab39b7dce61fa73f45e9972e59bd 100644
--- a/dev/tools/performance-toolkit/benchmark.jmx
+++ b/dev/tools/performance-toolkit/benchmark.jmx
@@ -316,7 +316,7 @@ props.put(&quot;category_name&quot;, vars.get(&quot;category_name&quot;));</stri
           <stringProp name="HTTPSampler.response_timeout"></stringProp>
           <stringProp name="HTTPSampler.protocol"></stringProp>
           <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp>
-          <stringProp name="HTTPSampler.path">${base_path}catalogsearch/result/?limit=30&amp;q=Simple</stringProp>
+          <stringProp name="HTTPSampler.path">${base_path}catalogsearch/result/index/?limit=30&amp;q=Simple</stringProp>
           <stringProp name="HTTPSampler.method">GET</stringProp>
           <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
           <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@@ -340,7 +340,7 @@ props.put(&quot;category_name&quot;, vars.get(&quot;category_name&quot;));</stri
           <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract product url keys" enabled="true">
             <stringProp name="RegexExtractor.useHeaders">false</stringProp>
             <stringProp name="RegexExtractor.refname">simple_products_url_keys</stringProp>
-            <stringProp name="RegexExtractor.regex">${base_path}(index.php/)?(simple.*)${url_suffix}&quot; title=&quot;[Ss]imple.*&quot;</stringProp>
+            <stringProp name="RegexExtractor.regex">&lt;a class=&quot;product-item-link&quot; href=&quot;http://${host}${base_path}(index.php/)?([^&apos;&quot;]+)${url_suffix}&quot;&gt;Simple</stringProp>
             <stringProp name="RegexExtractor.template">$2$</stringProp>
             <stringProp name="RegexExtractor.default"></stringProp>
             <stringProp name="RegexExtractor.match_number">-1</stringProp>
@@ -386,7 +386,7 @@ props.put(&quot;category_name&quot;, vars.get(&quot;category_name&quot;));</stri
             <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor: Extarct product title" enabled="true">
               <stringProp name="XPathExtractor.default"></stringProp>
               <stringProp name="XPathExtractor.refname">simple_product_title</stringProp>
-              <stringProp name="XPathExtractor.xpathQuery">.//*[@data-ui-id=&apos;page-title&apos;]/text()</stringProp>
+              <stringProp name="XPathExtractor.xpathQuery">.//*[@data-ui-id=&apos;page-title-wrapper&apos;]/text()</stringProp>
               <boolProp name="XPathExtractor.validate">false</boolProp>
               <boolProp name="XPathExtractor.tolerant">true</boolProp>
               <boolProp name="XPathExtractor.namespace">false</boolProp>
@@ -471,7 +471,7 @@ productList.add(productMap);                        </stringProp>
           <stringProp name="HTTPSampler.response_timeout"></stringProp>
           <stringProp name="HTTPSampler.protocol"></stringProp>
           <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp>
-          <stringProp name="HTTPSampler.path">${base_path}catalogsearch/result/?limit=30&amp;q=Configurable</stringProp>
+          <stringProp name="HTTPSampler.path">${base_path}catalogsearch/result/index/?limit=30&amp;q=Configurable</stringProp>
           <stringProp name="HTTPSampler.method">GET</stringProp>
           <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
           <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@@ -495,7 +495,7 @@ productList.add(productMap);                        </stringProp>
           <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract product url keys" enabled="true">
             <stringProp name="RegexExtractor.useHeaders">false</stringProp>
             <stringProp name="RegexExtractor.refname">configurable_products_url_keys</stringProp>
-            <stringProp name="RegexExtractor.regex">${base_path}(index.php/)?(configurable.*)${url_suffix}&quot; title=&quot;[Cc]onfigurable.*&quot;</stringProp>
+            <stringProp name="RegexExtractor.regex">&lt;a class=&quot;product-item-link&quot; href=&quot;http://${host}${base_path}(index.php/)?([^&apos;&quot;]+)${url_suffix}&quot;&gt;Configurable</stringProp>
             <stringProp name="RegexExtractor.template">$2$</stringProp>
             <stringProp name="RegexExtractor.default"></stringProp>
             <stringProp name="RegexExtractor.match_number">-1</stringProp>
@@ -541,7 +541,7 @@ productList.add(productMap);                        </stringProp>
             <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor: Extarct product title" enabled="true">
               <stringProp name="XPathExtractor.default"></stringProp>
               <stringProp name="XPathExtractor.refname">configurable_product_title</stringProp>
-              <stringProp name="XPathExtractor.xpathQuery">.//*[@data-ui-id=&apos;page-title&apos;]/text()</stringProp>
+              <stringProp name="XPathExtractor.xpathQuery">.//*[@data-ui-id=&apos;page-title-wrapper&apos;]/text()</stringProp>
               <boolProp name="XPathExtractor.validate">false</boolProp>
               <boolProp name="XPathExtractor.tolerant">true</boolProp>
               <boolProp name="XPathExtractor.namespace">false</boolProp>
@@ -550,7 +550,7 @@ productList.add(productMap);                        </stringProp>
             <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extarct product attribute id" enabled="true">
               <stringProp name="RegexExtractor.useHeaders">false</stringProp>
               <stringProp name="RegexExtractor.refname">configurable_product_attribute_id</stringProp>
-              <stringProp name="RegexExtractor.regex">&quot;spConfig&quot;:\{&quot;attributes&quot;:\{&quot;(\d+)&quot;</stringProp>
+              <stringProp name="RegexExtractor.regex">&quot;attributes&quot;:\{&quot;(\d+)&quot;</stringProp>
               <stringProp name="RegexExtractor.template">$1$</stringProp>
               <stringProp name="RegexExtractor.default"></stringProp>
               <stringProp name="RegexExtractor.match_number">1</stringProp>
@@ -1401,6 +1401,26 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
             <intProp name="Assertion.test_type">2</intProp>
           </ResponseAssertion>
           <hashTree/>
+          <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true">
+            <stringProp name="RegexExtractor.useHeaders">false</stringProp>
+            <stringProp name="RegexExtractor.refname">simple_product_1_form_action</stringProp>
+            <stringProp name="RegexExtractor.regex">&lt;form action=&quot;([^&apos;&quot;]+)&quot; method=&quot;post&quot; id=&quot;product_addtocart_form&quot;&gt;</stringProp>
+            <stringProp name="RegexExtractor.template">$1$</stringProp>
+            <stringProp name="RegexExtractor.default"></stringProp>
+            <stringProp name="RegexExtractor.match_number">1</stringProp>
+          </RegexExtractor>
+          <hashTree/>
+          <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true">
+            <collectionProp name="Asserion.test_strings">
+              <stringProp name="2845929">^.+$</stringProp>
+            </collectionProp>
+            <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
+            <boolProp name="Assertion.assume_success">false</boolProp>
+            <intProp name="Assertion.test_type">1</intProp>
+            <stringProp name="Assertion.scope">variable</stringProp>
+            <stringProp name="Scope.variable">simple_product_1_form_action</stringProp>
+          </ResponseAssertion>
+          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -1431,6 +1451,20 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
                 <boolProp name="HTTPArgument.use_equals">true</boolProp>
                 <stringProp name="Argument.name">qty</stringProp>
               </elementProp>
+              <elementProp name="isAjax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">isAjax</stringProp>
+              </elementProp>
+              <elementProp name="ajax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">ajax</stringProp>
+              </elementProp>
             </collectionProp>
           </elementProp>
           <stringProp name="HTTPSampler.domain"></stringProp>
@@ -1439,7 +1473,7 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
           <stringProp name="HTTPSampler.response_timeout"></stringProp>
           <stringProp name="HTTPSampler.protocol">http</stringProp>
           <stringProp name="HTTPSampler.contentEncoding"></stringProp>
-          <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add</stringProp>
+          <stringProp name="HTTPSampler.path">${simple_product_1_form_action}</stringProp>
           <stringProp name="HTTPSampler.method">POST</stringProp>
           <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
           <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@@ -1468,17 +1502,6 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
             <intProp name="Assertion.test_type">6</intProp>
           </ResponseAssertion>
           <hashTree/>
-          <XPathAssertion guiclass="XPathAssertionGui" testclass="XPathAssertion" testname="XPath Assertion" enabled="true">
-            <boolProp name="XPath.negate">false</boolProp>
-            <stringProp name="XPath.xpath">count(//*[@class=&apos;cart item&apos;])=1</stringProp>
-            <boolProp name="XPath.validate">false</boolProp>
-            <boolProp name="XPath.whitespace">false</boolProp>
-            <boolProp name="XPath.tolerant">true</boolProp>
-            <boolProp name="XPath.namespace">false</boolProp>
-            <boolProp name="XPath.show_warnings">true</boolProp>
-            <boolProp name="XPath.report_errors">true</boolProp>
-          </XPathAssertion>
-          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -1516,6 +1539,26 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
             <intProp name="Assertion.test_type">2</intProp>
           </ResponseAssertion>
           <hashTree/>
+          <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true">
+            <stringProp name="RegexExtractor.useHeaders">false</stringProp>
+            <stringProp name="RegexExtractor.refname">simple_product_2_form_action</stringProp>
+            <stringProp name="RegexExtractor.regex">&lt;form action=&quot;([^&apos;&quot;]+)&quot; method=&quot;post&quot; id=&quot;product_addtocart_form&quot;&gt;</stringProp>
+            <stringProp name="RegexExtractor.template">$1$</stringProp>
+            <stringProp name="RegexExtractor.default"></stringProp>
+            <stringProp name="RegexExtractor.match_number">1</stringProp>
+          </RegexExtractor>
+          <hashTree/>
+          <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true">
+            <collectionProp name="Asserion.test_strings">
+              <stringProp name="2845929">^.+$</stringProp>
+            </collectionProp>
+            <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
+            <boolProp name="Assertion.assume_success">false</boolProp>
+            <intProp name="Assertion.test_type">1</intProp>
+            <stringProp name="Assertion.scope">variable</stringProp>
+            <stringProp name="Scope.variable">simple_product_2_form_action</stringProp>
+          </ResponseAssertion>
+          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -1546,6 +1589,20 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
                 <boolProp name="HTTPArgument.use_equals">true</boolProp>
                 <stringProp name="Argument.name">qty</stringProp>
               </elementProp>
+              <elementProp name="isAjax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">isAjax</stringProp>
+              </elementProp>
+              <elementProp name="ajax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">ajax</stringProp>
+              </elementProp>
             </collectionProp>
           </elementProp>
           <stringProp name="HTTPSampler.domain"></stringProp>
@@ -1554,7 +1611,7 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
           <stringProp name="HTTPSampler.response_timeout"></stringProp>
           <stringProp name="HTTPSampler.protocol">http</stringProp>
           <stringProp name="HTTPSampler.contentEncoding"></stringProp>
-          <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add</stringProp>
+          <stringProp name="HTTPSampler.path">${simple_product_2_form_action}</stringProp>
           <stringProp name="HTTPSampler.method">POST</stringProp>
           <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
           <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@@ -1583,17 +1640,6 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
             <intProp name="Assertion.test_type">6</intProp>
           </ResponseAssertion>
           <hashTree/>
-          <XPathAssertion guiclass="XPathAssertionGui" testclass="XPathAssertion" testname="XPath Assertion" enabled="true">
-            <boolProp name="XPath.negate">false</boolProp>
-            <stringProp name="XPath.xpath">count(//*[@class=&apos;cart item&apos;])=2</stringProp>
-            <boolProp name="XPath.validate">false</boolProp>
-            <boolProp name="XPath.whitespace">false</boolProp>
-            <boolProp name="XPath.tolerant">true</boolProp>
-            <boolProp name="XPath.namespace">false</boolProp>
-            <boolProp name="XPath.show_warnings">true</boolProp>
-            <boolProp name="XPath.report_errors">true</boolProp>
-          </XPathAssertion>
-          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -1631,6 +1677,26 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
             <intProp name="Assertion.test_type">2</intProp>
           </ResponseAssertion>
           <hashTree/>
+          <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true">
+            <stringProp name="RegexExtractor.useHeaders">false</stringProp>
+            <stringProp name="RegexExtractor.refname">configurable_product_form_action</stringProp>
+            <stringProp name="RegexExtractor.regex">&lt;form action=&quot;([^&apos;&quot;]+)&quot; method=&quot;post&quot; id=&quot;product_addtocart_form&quot;&gt;</stringProp>
+            <stringProp name="RegexExtractor.template">$1$</stringProp>
+            <stringProp name="RegexExtractor.default"></stringProp>
+            <stringProp name="RegexExtractor.match_number">1</stringProp>
+          </RegexExtractor>
+          <hashTree/>
+          <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true">
+            <collectionProp name="Asserion.test_strings">
+              <stringProp name="2845929">^.+$</stringProp>
+            </collectionProp>
+            <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
+            <boolProp name="Assertion.assume_success">false</boolProp>
+            <intProp name="Assertion.test_type">1</intProp>
+            <stringProp name="Assertion.scope">variable</stringProp>
+            <stringProp name="Scope.variable">configurable_product_form_action</stringProp>
+          </ResponseAssertion>
+          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -1668,6 +1734,20 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
                 <boolProp name="HTTPArgument.use_equals">true</boolProp>
                 <stringProp name="Argument.name">super_attribute[${configurable_attribute_id}]</stringProp>
               </elementProp>
+              <elementProp name="isAjax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">isAjax</stringProp>
+              </elementProp>
+              <elementProp name="ajax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">ajax</stringProp>
+              </elementProp>
             </collectionProp>
           </elementProp>
           <stringProp name="HTTPSampler.domain"></stringProp>
@@ -1676,7 +1756,7 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
           <stringProp name="HTTPSampler.response_timeout"></stringProp>
           <stringProp name="HTTPSampler.protocol">http</stringProp>
           <stringProp name="HTTPSampler.contentEncoding"></stringProp>
-          <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add</stringProp>
+          <stringProp name="HTTPSampler.path">${configurable_product_form_action}</stringProp>
           <stringProp name="HTTPSampler.method">POST</stringProp>
           <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
           <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@@ -1705,17 +1785,6 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
             <intProp name="Assertion.test_type">6</intProp>
           </ResponseAssertion>
           <hashTree/>
-          <XPathAssertion guiclass="XPathAssertionGui" testclass="XPathAssertion" testname="XPath Assertion" enabled="true">
-            <boolProp name="XPath.negate">false</boolProp>
-            <stringProp name="XPath.xpath">count(//*[@class=&apos;cart item&apos;])=3</stringProp>
-            <boolProp name="XPath.validate">false</boolProp>
-            <boolProp name="XPath.whitespace">false</boolProp>
-            <boolProp name="XPath.tolerant">true</boolProp>
-            <boolProp name="XPath.namespace">false</boolProp>
-            <boolProp name="XPath.show_warnings">true</boolProp>
-            <boolProp name="XPath.report_errors">true</boolProp>
-          </XPathAssertion>
-          <hashTree/>
         </hashTree>
       </hashTree>
       <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Guest Checkout" enabled="true">
@@ -1882,6 +1951,26 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
             <intProp name="Assertion.test_type">2</intProp>
           </ResponseAssertion>
           <hashTree/>
+          <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true">
+            <stringProp name="RegexExtractor.useHeaders">false</stringProp>
+            <stringProp name="RegexExtractor.refname">simple_product_1_form_action</stringProp>
+            <stringProp name="RegexExtractor.regex">&lt;form action=&quot;([^&apos;&quot;]+)&quot; method=&quot;post&quot; id=&quot;product_addtocart_form&quot;&gt;</stringProp>
+            <stringProp name="RegexExtractor.template">$1$</stringProp>
+            <stringProp name="RegexExtractor.default"></stringProp>
+            <stringProp name="RegexExtractor.match_number">1</stringProp>
+          </RegexExtractor>
+          <hashTree/>
+          <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true">
+            <collectionProp name="Asserion.test_strings">
+              <stringProp name="2845929">^.+$</stringProp>
+            </collectionProp>
+            <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
+            <boolProp name="Assertion.assume_success">false</boolProp>
+            <intProp name="Assertion.test_type">1</intProp>
+            <stringProp name="Assertion.scope">variable</stringProp>
+            <stringProp name="Scope.variable">simple_product_1_form_action</stringProp>
+          </ResponseAssertion>
+          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -1912,6 +2001,20 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
                 <boolProp name="HTTPArgument.use_equals">true</boolProp>
                 <stringProp name="Argument.name">qty</stringProp>
               </elementProp>
+              <elementProp name="isAjax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">isAjax</stringProp>
+              </elementProp>
+              <elementProp name="ajax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">ajax</stringProp>
+              </elementProp>
             </collectionProp>
           </elementProp>
           <stringProp name="HTTPSampler.domain"></stringProp>
@@ -1920,7 +2023,7 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
           <stringProp name="HTTPSampler.response_timeout"></stringProp>
           <stringProp name="HTTPSampler.protocol">http</stringProp>
           <stringProp name="HTTPSampler.contentEncoding"></stringProp>
-          <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add</stringProp>
+          <stringProp name="HTTPSampler.path">${simple_product_1_form_action}</stringProp>
           <stringProp name="HTTPSampler.method">POST</stringProp>
           <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
           <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@@ -1949,17 +2052,6 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
             <intProp name="Assertion.test_type">6</intProp>
           </ResponseAssertion>
           <hashTree/>
-          <XPathAssertion guiclass="XPathAssertionGui" testclass="XPathAssertion" testname="XPath Assertion" enabled="true">
-            <boolProp name="XPath.negate">false</boolProp>
-            <stringProp name="XPath.xpath">count(//*[@class=&apos;cart item&apos;])=1</stringProp>
-            <boolProp name="XPath.validate">false</boolProp>
-            <boolProp name="XPath.whitespace">false</boolProp>
-            <boolProp name="XPath.tolerant">true</boolProp>
-            <boolProp name="XPath.namespace">false</boolProp>
-            <boolProp name="XPath.show_warnings">true</boolProp>
-            <boolProp name="XPath.report_errors">true</boolProp>
-          </XPathAssertion>
-          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -1997,6 +2089,26 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
             <intProp name="Assertion.test_type">2</intProp>
           </ResponseAssertion>
           <hashTree/>
+          <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true">
+            <stringProp name="RegexExtractor.useHeaders">false</stringProp>
+            <stringProp name="RegexExtractor.refname">simple_product_2_form_action</stringProp>
+            <stringProp name="RegexExtractor.regex">&lt;form action=&quot;([^&apos;&quot;]+)&quot; method=&quot;post&quot; id=&quot;product_addtocart_form&quot;&gt;</stringProp>
+            <stringProp name="RegexExtractor.template">$1$</stringProp>
+            <stringProp name="RegexExtractor.default"></stringProp>
+            <stringProp name="RegexExtractor.match_number">1</stringProp>
+          </RegexExtractor>
+          <hashTree/>
+          <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true">
+            <collectionProp name="Asserion.test_strings">
+              <stringProp name="2845929">^.+$</stringProp>
+            </collectionProp>
+            <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
+            <boolProp name="Assertion.assume_success">false</boolProp>
+            <intProp name="Assertion.test_type">1</intProp>
+            <stringProp name="Assertion.scope">variable</stringProp>
+            <stringProp name="Scope.variable">simple_product_2_form_action</stringProp>
+          </ResponseAssertion>
+          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -2027,6 +2139,20 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
                 <boolProp name="HTTPArgument.use_equals">true</boolProp>
                 <stringProp name="Argument.name">qty</stringProp>
               </elementProp>
+              <elementProp name="isAjax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">isAjax</stringProp>
+              </elementProp>
+              <elementProp name="ajax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">ajax</stringProp>
+              </elementProp>
             </collectionProp>
           </elementProp>
           <stringProp name="HTTPSampler.domain"></stringProp>
@@ -2035,7 +2161,7 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
           <stringProp name="HTTPSampler.response_timeout"></stringProp>
           <stringProp name="HTTPSampler.protocol">http</stringProp>
           <stringProp name="HTTPSampler.contentEncoding"></stringProp>
-          <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add</stringProp>
+          <stringProp name="HTTPSampler.path">${simple_product_2_form_action}</stringProp>
           <stringProp name="HTTPSampler.method">POST</stringProp>
           <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
           <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@@ -2064,17 +2190,6 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
             <intProp name="Assertion.test_type">6</intProp>
           </ResponseAssertion>
           <hashTree/>
-          <XPathAssertion guiclass="XPathAssertionGui" testclass="XPathAssertion" testname="XPath Assertion" enabled="true">
-            <boolProp name="XPath.negate">false</boolProp>
-            <stringProp name="XPath.xpath">count(//*[@class=&apos;cart item&apos;])=2</stringProp>
-            <boolProp name="XPath.validate">false</boolProp>
-            <boolProp name="XPath.whitespace">false</boolProp>
-            <boolProp name="XPath.tolerant">true</boolProp>
-            <boolProp name="XPath.namespace">false</boolProp>
-            <boolProp name="XPath.show_warnings">true</boolProp>
-            <boolProp name="XPath.report_errors">true</boolProp>
-          </XPathAssertion>
-          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -2112,6 +2227,26 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
             <intProp name="Assertion.test_type">2</intProp>
           </ResponseAssertion>
           <hashTree/>
+          <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true">
+            <stringProp name="RegexExtractor.useHeaders">false</stringProp>
+            <stringProp name="RegexExtractor.refname">configurable_product_form_action</stringProp>
+            <stringProp name="RegexExtractor.regex">&lt;form action=&quot;([^&apos;&quot;]+)&quot; method=&quot;post&quot; id=&quot;product_addtocart_form&quot;&gt;</stringProp>
+            <stringProp name="RegexExtractor.template">$1$</stringProp>
+            <stringProp name="RegexExtractor.default"></stringProp>
+            <stringProp name="RegexExtractor.match_number">1</stringProp>
+          </RegexExtractor>
+          <hashTree/>
+          <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true">
+            <collectionProp name="Asserion.test_strings">
+              <stringProp name="2845929">^.+$</stringProp>
+            </collectionProp>
+            <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
+            <boolProp name="Assertion.assume_success">false</boolProp>
+            <intProp name="Assertion.test_type">1</intProp>
+            <stringProp name="Assertion.scope">variable</stringProp>
+            <stringProp name="Scope.variable">configurable_product_form_action</stringProp>
+          </ResponseAssertion>
+          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -2149,6 +2284,20 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
                 <boolProp name="HTTPArgument.use_equals">true</boolProp>
                 <stringProp name="Argument.name">super_attribute[${configurable_attribute_id}]</stringProp>
               </elementProp>
+              <elementProp name="isAjax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">isAjax</stringProp>
+              </elementProp>
+              <elementProp name="ajax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">ajax</stringProp>
+              </elementProp>
             </collectionProp>
           </elementProp>
           <stringProp name="HTTPSampler.domain"></stringProp>
@@ -2157,7 +2306,7 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
           <stringProp name="HTTPSampler.response_timeout"></stringProp>
           <stringProp name="HTTPSampler.protocol">http</stringProp>
           <stringProp name="HTTPSampler.contentEncoding"></stringProp>
-          <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add</stringProp>
+          <stringProp name="HTTPSampler.path">${configurable_product_form_action}</stringProp>
           <stringProp name="HTTPSampler.method">POST</stringProp>
           <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
           <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@@ -2186,17 +2335,6 @@ vars.put(&quot;category_name&quot;, props.get(&quot;category_name&quot;));</stri
             <intProp name="Assertion.test_type">6</intProp>
           </ResponseAssertion>
           <hashTree/>
-          <XPathAssertion guiclass="XPathAssertionGui" testclass="XPathAssertion" testname="XPath Assertion" enabled="true">
-            <boolProp name="XPath.negate">false</boolProp>
-            <stringProp name="XPath.xpath">count(//*[@class=&apos;cart item&apos;])=3</stringProp>
-            <boolProp name="XPath.validate">false</boolProp>
-            <boolProp name="XPath.whitespace">false</boolProp>
-            <boolProp name="XPath.tolerant">true</boolProp>
-            <boolProp name="XPath.namespace">false</boolProp>
-            <boolProp name="XPath.show_warnings">true</boolProp>
-            <boolProp name="XPath.report_errors">true</boolProp>
-          </XPathAssertion>
-          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -2932,6 +3070,26 @@ if (emailsCount &lt; 1) {
             <intProp name="Assertion.test_type">2</intProp>
           </ResponseAssertion>
           <hashTree/>
+          <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true">
+            <stringProp name="RegexExtractor.useHeaders">false</stringProp>
+            <stringProp name="RegexExtractor.refname">simple_product_1_form_action</stringProp>
+            <stringProp name="RegexExtractor.regex">&lt;form action=&quot;([^&apos;&quot;]+)&quot; method=&quot;post&quot; id=&quot;product_addtocart_form&quot;&gt;</stringProp>
+            <stringProp name="RegexExtractor.template">$1$</stringProp>
+            <stringProp name="RegexExtractor.default"></stringProp>
+            <stringProp name="RegexExtractor.match_number">1</stringProp>
+          </RegexExtractor>
+          <hashTree/>
+          <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true">
+            <collectionProp name="Asserion.test_strings">
+              <stringProp name="2845929">^.+$</stringProp>
+            </collectionProp>
+            <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
+            <boolProp name="Assertion.assume_success">false</boolProp>
+            <intProp name="Assertion.test_type">1</intProp>
+            <stringProp name="Assertion.scope">variable</stringProp>
+            <stringProp name="Scope.variable">simple_product_1_form_action</stringProp>
+          </ResponseAssertion>
+          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -2962,6 +3120,20 @@ if (emailsCount &lt; 1) {
                 <boolProp name="HTTPArgument.use_equals">true</boolProp>
                 <stringProp name="Argument.name">qty</stringProp>
               </elementProp>
+              <elementProp name="isAjax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">isAjax</stringProp>
+              </elementProp>
+              <elementProp name="ajax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">ajax</stringProp>
+              </elementProp>
             </collectionProp>
           </elementProp>
           <stringProp name="HTTPSampler.domain"></stringProp>
@@ -2970,7 +3142,7 @@ if (emailsCount &lt; 1) {
           <stringProp name="HTTPSampler.response_timeout"></stringProp>
           <stringProp name="HTTPSampler.protocol">http</stringProp>
           <stringProp name="HTTPSampler.contentEncoding"></stringProp>
-          <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add</stringProp>
+          <stringProp name="HTTPSampler.path">${simple_product_1_form_action}</stringProp>
           <stringProp name="HTTPSampler.method">POST</stringProp>
           <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
           <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@@ -2999,17 +3171,6 @@ if (emailsCount &lt; 1) {
             <intProp name="Assertion.test_type">6</intProp>
           </ResponseAssertion>
           <hashTree/>
-          <XPathAssertion guiclass="XPathAssertionGui" testclass="XPathAssertion" testname="XPath Assertion" enabled="true">
-            <boolProp name="XPath.negate">false</boolProp>
-            <stringProp name="XPath.xpath">count(//*[@class=&apos;cart item&apos;])=1</stringProp>
-            <boolProp name="XPath.validate">false</boolProp>
-            <boolProp name="XPath.whitespace">false</boolProp>
-            <boolProp name="XPath.tolerant">true</boolProp>
-            <boolProp name="XPath.namespace">false</boolProp>
-            <boolProp name="XPath.show_warnings">true</boolProp>
-            <boolProp name="XPath.report_errors">true</boolProp>
-          </XPathAssertion>
-          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -3047,6 +3208,26 @@ if (emailsCount &lt; 1) {
             <intProp name="Assertion.test_type">2</intProp>
           </ResponseAssertion>
           <hashTree/>
+          <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true">
+            <stringProp name="RegexExtractor.useHeaders">false</stringProp>
+            <stringProp name="RegexExtractor.refname">simple_product_2_form_action</stringProp>
+            <stringProp name="RegexExtractor.regex">&lt;form action=&quot;([^&apos;&quot;]+)&quot; method=&quot;post&quot; id=&quot;product_addtocart_form&quot;&gt;</stringProp>
+            <stringProp name="RegexExtractor.template">$1$</stringProp>
+            <stringProp name="RegexExtractor.default"></stringProp>
+            <stringProp name="RegexExtractor.match_number">1</stringProp>
+          </RegexExtractor>
+          <hashTree/>
+          <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true">
+            <collectionProp name="Asserion.test_strings">
+              <stringProp name="2845929">^.+$</stringProp>
+            </collectionProp>
+            <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
+            <boolProp name="Assertion.assume_success">false</boolProp>
+            <intProp name="Assertion.test_type">1</intProp>
+            <stringProp name="Assertion.scope">variable</stringProp>
+            <stringProp name="Scope.variable">simple_product_2_form_action</stringProp>
+          </ResponseAssertion>
+          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -3077,6 +3258,20 @@ if (emailsCount &lt; 1) {
                 <boolProp name="HTTPArgument.use_equals">true</boolProp>
                 <stringProp name="Argument.name">qty</stringProp>
               </elementProp>
+              <elementProp name="isAjax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">isAjax</stringProp>
+              </elementProp>
+              <elementProp name="ajax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">ajax</stringProp>
+              </elementProp>
             </collectionProp>
           </elementProp>
           <stringProp name="HTTPSampler.domain"></stringProp>
@@ -3085,7 +3280,7 @@ if (emailsCount &lt; 1) {
           <stringProp name="HTTPSampler.response_timeout"></stringProp>
           <stringProp name="HTTPSampler.protocol">http</stringProp>
           <stringProp name="HTTPSampler.contentEncoding"></stringProp>
-          <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add</stringProp>
+          <stringProp name="HTTPSampler.path">${simple_product_2_form_action}</stringProp>
           <stringProp name="HTTPSampler.method">POST</stringProp>
           <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
           <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@@ -3114,17 +3309,6 @@ if (emailsCount &lt; 1) {
             <intProp name="Assertion.test_type">6</intProp>
           </ResponseAssertion>
           <hashTree/>
-          <XPathAssertion guiclass="XPathAssertionGui" testclass="XPathAssertion" testname="XPath Assertion" enabled="true">
-            <boolProp name="XPath.negate">false</boolProp>
-            <stringProp name="XPath.xpath">count(//*[@class=&apos;cart item&apos;])=2</stringProp>
-            <boolProp name="XPath.validate">false</boolProp>
-            <boolProp name="XPath.whitespace">false</boolProp>
-            <boolProp name="XPath.tolerant">true</boolProp>
-            <boolProp name="XPath.namespace">false</boolProp>
-            <boolProp name="XPath.show_warnings">true</boolProp>
-            <boolProp name="XPath.report_errors">true</boolProp>
-          </XPathAssertion>
-          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -3162,6 +3346,26 @@ if (emailsCount &lt; 1) {
             <intProp name="Assertion.test_type">2</intProp>
           </ResponseAssertion>
           <hashTree/>
+          <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true">
+            <stringProp name="RegexExtractor.useHeaders">false</stringProp>
+            <stringProp name="RegexExtractor.refname">configurable_product_form_action</stringProp>
+            <stringProp name="RegexExtractor.regex">&lt;form action=&quot;([^&apos;&quot;]+)&quot; method=&quot;post&quot; id=&quot;product_addtocart_form&quot;&gt;</stringProp>
+            <stringProp name="RegexExtractor.template">$1$</stringProp>
+            <stringProp name="RegexExtractor.default"></stringProp>
+            <stringProp name="RegexExtractor.match_number">1</stringProp>
+          </RegexExtractor>
+          <hashTree/>
+          <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true">
+            <collectionProp name="Asserion.test_strings">
+              <stringProp name="2845929">^.+$</stringProp>
+            </collectionProp>
+            <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
+            <boolProp name="Assertion.assume_success">false</boolProp>
+            <intProp name="Assertion.test_type">1</intProp>
+            <stringProp name="Assertion.scope">variable</stringProp>
+            <stringProp name="Scope.variable">configurable_product_form_action</stringProp>
+          </ResponseAssertion>
+          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
@@ -3199,6 +3403,20 @@ if (emailsCount &lt; 1) {
                 <boolProp name="HTTPArgument.use_equals">true</boolProp>
                 <stringProp name="Argument.name">super_attribute[${configurable_attribute_id}]</stringProp>
               </elementProp>
+              <elementProp name="isAjax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">isAjax</stringProp>
+              </elementProp>
+              <elementProp name="ajax" elementType="HTTPArgument">
+                <boolProp name="HTTPArgument.always_encode">false</boolProp>
+                <stringProp name="Argument.value">true</stringProp>
+                <stringProp name="Argument.metadata">=</stringProp>
+                <boolProp name="HTTPArgument.use_equals">true</boolProp>
+                <stringProp name="Argument.name">ajax</stringProp>
+              </elementProp>
             </collectionProp>
           </elementProp>
           <stringProp name="HTTPSampler.domain"></stringProp>
@@ -3207,7 +3425,7 @@ if (emailsCount &lt; 1) {
           <stringProp name="HTTPSampler.response_timeout"></stringProp>
           <stringProp name="HTTPSampler.protocol">http</stringProp>
           <stringProp name="HTTPSampler.contentEncoding"></stringProp>
-          <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add</stringProp>
+          <stringProp name="HTTPSampler.path">${configurable_product_form_action}</stringProp>
           <stringProp name="HTTPSampler.method">POST</stringProp>
           <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
           <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@@ -3236,17 +3454,6 @@ if (emailsCount &lt; 1) {
             <intProp name="Assertion.test_type">6</intProp>
           </ResponseAssertion>
           <hashTree/>
-          <XPathAssertion guiclass="XPathAssertionGui" testclass="XPathAssertion" testname="XPath Assertion" enabled="true">
-            <boolProp name="XPath.negate">false</boolProp>
-            <stringProp name="XPath.xpath">count(//*[@class=&apos;cart item&apos;])=3</stringProp>
-            <boolProp name="XPath.validate">false</boolProp>
-            <boolProp name="XPath.whitespace">false</boolProp>
-            <boolProp name="XPath.tolerant">true</boolProp>
-            <boolProp name="XPath.namespace">false</boolProp>
-            <boolProp name="XPath.show_warnings">true</boolProp>
-            <boolProp name="XPath.report_errors">true</boolProp>
-          </XPathAssertion>
-          <hashTree/>
         </hashTree>
         <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true">
           <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp>
diff --git a/dev/tools/performance-toolkit/generate.php b/dev/tools/performance-toolkit/generate.php
index 43a4d61cc09621160a16435766c723f5fbabb5b2..861abee07ef81a10ceee9e80fc2aa9ef91ccb20d 100644
--- a/dev/tools/performance-toolkit/generate.php
+++ b/dev/tools/performance-toolkit/generate.php
@@ -41,6 +41,18 @@ try {
         echo ' |- ' . $label . ': ' . $config->getValue($configKey) . PHP_EOL;
     }
 
+    /** @var $config \Magento\Indexer\Model\Config */
+    $config = $application->getObjectManager()->get('Magento\Indexer\Model\Config');
+    $indexerListIds = $config->getIndexers();
+    /** @var $indexerRegistry \Magento\Indexer\Model\IndexerRegistry */
+    $indexerRegistry = $application->getObjectManager()->create('Magento\Indexer\Model\IndexerRegistry');
+    $indexersState = [];
+    foreach ($indexerListIds as $key => $indexerId) {
+        $indexer = $indexerRegistry->get($indexerId['indexer_id']);
+        $indexersState[$indexerId['indexer_id']] = $indexer->isScheduled();
+        $indexer->setScheduled(true);
+    }
+
     foreach ($application->getFixtures() as $fixture) {
         echo $fixture->getActionTitle() . '... ';
         $startTime = microtime(true);
@@ -50,6 +62,12 @@ try {
         echo ' done in ' . gmdate('H:i:s', $resultTime) . PHP_EOL;
     }
 
+    foreach ($indexerListIds as $indexerId) {
+        /** @var $indexer \Magento\Indexer\Model\Indexer */
+        $indexer = $indexerRegistry->get($indexerId['indexer_id']);
+        $indexer->setScheduled($indexersState[$indexerId['indexer_id']]);
+    }
+
     $application->reindex();
     $totalEndTime = microtime(true);
     $totalResultTime = $totalEndTime - $totalStartTime;
diff --git a/lib/internal/Magento/Framework/Api/SearchCriteria.php b/lib/internal/Magento/Framework/Api/SearchCriteria.php
index 727be2cac88b47b98e73fc919a2cb47057997433..b98908fcb85d6756df137cb48d526fed1b3ce184 100644
--- a/lib/internal/Magento/Framework/Api/SearchCriteria.php
+++ b/lib/internal/Magento/Framework/Api/SearchCriteria.php
@@ -15,7 +15,7 @@ class SearchCriteria extends AbstractSimpleObject implements SearchCriteriaInter
     /**#@+
      * Constants for Data Object keys
      */
-    const FILTER_GROUPS = 'filterGroups';
+    const FILTER_GROUPS = 'filter_groups';
     const SORT_ORDERS = 'sort_orders';
     const PAGE_SIZE = 'page_size';
     const CURRENT_PAGE = 'current_page';
diff --git a/lib/internal/Magento/Framework/Code/Minifier/Adapter/Css/CssMinifier.php b/lib/internal/Magento/Framework/Code/Minifier/Adapter/Css/CssMinifier.php
index dddf0a6e4c00605e256cb9e1f349ea9c050df343..e1d4d01942333670ac1799df0820c589520b8118 100644
--- a/lib/internal/Magento/Framework/Code/Minifier/Adapter/Css/CssMinifier.php
+++ b/lib/internal/Magento/Framework/Code/Minifier/Adapter/Css/CssMinifier.php
@@ -11,6 +11,11 @@ use Magento\Framework\Code\Minifier\AdapterInterface;
 
 class CssMinifier implements AdapterInterface
 {
+    /**
+     * 'pcre.recursion_limit' value for CSSMin minification
+     */
+    const PCRE_RECURSION_LIMIT = 1000;
+
     /**
      * @var CSSmin
      */
@@ -32,6 +37,10 @@ class CssMinifier implements AdapterInterface
      */
     public function minify($content)
     {
-        return $this->cssMinifier->run($content);
+        $pcreRecursionLimit = ini_get('pcre.recursion_limit');
+        ini_set('pcre.recursion_limit', self::PCRE_RECURSION_LIMIT);
+        $result = $this->cssMinifier->run($content);
+        ini_set('pcre.recursion_limit', $pcreRecursionLimit);
+        return $result;
     }
 }