diff --git a/.gitignore b/.gitignore
index 1dc24183ad30092742a351bd094b4ae5573052be..12af626be05dba61c6b6f5a223a6b4a1ed2c6926 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,5 +46,5 @@ atlassian*
 
 /var/*
 !/var/.htaccess
-/vendor
+/vendor/*
 !/vendor/.htaccess
diff --git a/app/code/Magento/Backend/view/adminhtml/templates/system/search.phtml b/app/code/Magento/Backend/view/adminhtml/templates/system/search.phtml
index 378e72e42d8ab582d5b97a9af035c9198b46a863..dfe18c014599d674067c3a84c7b16a9c36f08cea 100644
--- a/app/code/Magento/Backend/view/adminhtml/templates/system/search.phtml
+++ b/app/code/Magento/Backend/view/adminhtml/templates/system/search.phtml
@@ -28,16 +28,16 @@
     <script data-template="search-suggest" type="text/x-magento-template">
         <ul class="search-global-menu">
         <li class="item">
-            <a href="<?php /* @escapeNotVerified */ echo $block->getURL('catalog/product/index/'); ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Products</a>
+            <a id="searchPreviewProducts" href="<?php /* @escapeNotVerified */ echo $block->getURL('catalog/product/index/'); ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Products</a>
         </li>
         <li class="item">
-            <a href="<?php /* @escapeNotVerified */ echo $block->getURL('sales/order/index/'); ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Orders</a>
+            <a id="searchPreviewOrders" href="<?php /* @escapeNotVerified */ echo $block->getURL('sales/order/index/'); ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Orders</a>
         </li>
         <li class="item">
-            <a href="<?php /* @escapeNotVerified */ echo $block->getURL('customer/index/index/'); ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Customers</a>
+            <a id="searchPreviewCustomers" href="<?php /* @escapeNotVerified */ echo $block->getURL('customer/index/index/'); ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Customers</a>
         </li>
         <li class="item">
-            <a href="<?php /* @escapeNotVerified */ echo $block->getURL('cms/page/index/'); ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Pages</a>
+            <a id="searchPreviewPages" href="<?php /* @escapeNotVerified */ echo $block->getURL('cms/page/index/'); ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Pages</a>
         </li>
             <% if (data.items.length) { %>
             <% _.each(data.items, function(value){ %>
diff --git a/app/code/Magento/Backup/Helper/Data.php b/app/code/Magento/Backup/Helper/Data.php
index 7448f7e520c135a31f1012f4e582a07b66aec294..4a35c12de46c2c8357bdd4d03182f74967faa9a1 100644
--- a/app/code/Magento/Backup/Helper/Data.php
+++ b/app/code/Magento/Backup/Helper/Data.php
@@ -122,7 +122,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
             \Magento\Framework\Backup\Factory::TYPE_SYSTEM_SNAPSHOT => 'tgz',
             \Magento\Framework\Backup\Factory::TYPE_SNAPSHOT_WITHOUT_MEDIA => 'tgz',
             \Magento\Framework\Backup\Factory::TYPE_MEDIA => 'tgz',
-            \Magento\Framework\Backup\Factory::TYPE_DB => 'gz'
+            \Magento\Framework\Backup\Factory::TYPE_DB => 'sql'
         ];
     }
 
diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Database.php b/app/code/Magento/MediaStorage/Model/File/Storage/Database.php
index a2fa8f11bd4f0810d31999a5634a3a24012cdb05..aeff2c2b266058d8f31f921e1a943b2b152865c7 100644
--- a/app/code/Magento/MediaStorage/Model/File/Storage/Database.php
+++ b/app/code/Magento/MediaStorage/Model/File/Storage/Database.php
@@ -41,6 +41,13 @@ class Database extends \Magento\MediaStorage\Model\File\Storage\Database\Abstrac
      */
     protected $_mediaHelper;
 
+    /**
+     * Store media base directory path
+     *
+     * @var string
+     */
+    protected $mediaBaseDirectory = null;
+
     /**
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
@@ -352,4 +359,17 @@ class Database extends \Magento\MediaStorage\Model\File\Storage\Database\Abstrac
 
         return $this;
     }
+
+    /**
+     * Retrieve media base directory path
+     *
+     * @return string
+     */
+    public function getMediaBaseDirectory()
+    {
+        if ($this->mediaBaseDirectory === null) {
+            $this->mediaBaseDirectory = $this->_coreFileStorageDb->getMediaBaseDir();
+        }
+        return $this->mediaBaseDirectory;
+    }
 }
diff --git a/app/code/Magento/Search/view/adminhtml/ui_component/search_synonyms_form.xml b/app/code/Magento/Search/view/adminhtml/ui_component/search_synonyms_form.xml
index 35e94ba04c30d9bade627fb34bdb4139fb7454be..004f6bd99960f4a9a5a0889d5ec74234127007c2 100644
--- a/app/code/Magento/Search/view/adminhtml/ui_component/search_synonyms_form.xml
+++ b/app/code/Magento/Search/view/adminhtml/ui_component/search_synonyms_form.xml
@@ -102,7 +102,6 @@
                 <item name="config" xsi:type="array">
                     <item name="additionalClasses" xsi:type="string">admin__field-no-label</item>
                     <item name="description" xsi:type="string" translate="true">Merge existing synonyms</item>
-                    <item name="dataType" xsi:type="string">boolean</item>
                     <item name="default" xsi:type="boolean">false</item>
                     <item name="formElement" xsi:type="string">checkbox</item>
                     <item name="dataScope" xsi:type="string">mergeOnConflict</item>
@@ -110,6 +109,10 @@
                     <item name="tooltip" xsi:type="array">
                         <item name="description" xsi:type="string" translate="true">Automatically merges synonyms in groups that share the same scope. If you check this box and you add one or more of the same terms to different synonym groups in the same scope, automatically merges all the terms to one group. If this isn't what you want, uncheck the box and an error displays if you try to add the same terms.</item>
                     </item>
+                    <item name="valueMap" xsi:type="array">
+                        <item name="true" xsi:type="boolean">true</item>
+                        <item name="false" xsi:type="boolean">false</item>
+                    </item>
                 </item>
             </argument>
         </field>
diff --git a/app/code/Magento/Theme/Model/Theme/Registration.php b/app/code/Magento/Theme/Model/Theme/Registration.php
index add61132ffafae4e6ee9f729f7eda6ebae725b03..d19cb2071aff1ea094d395a5e9ae088348eef947 100644
--- a/app/code/Magento/Theme/Model/Theme/Registration.php
+++ b/app/code/Magento/Theme/Model/Theme/Registration.php
@@ -68,6 +68,7 @@ class Registration
     public function register()
     {
         $this->_themeCollection->clear();
+
         foreach ($this->_themeCollection as $theme) {
             $this->_registerThemeRecursively($theme);
         }
diff --git a/app/code/Magento/Theme/Observer/ThemeRegistrationObserver.php b/app/code/Magento/Theme/Observer/ThemeRegistrationObserver.php
deleted file mode 100644
index 5c647753eaddc4cde5e77eb3c8629b7fd503f839..0000000000000000000000000000000000000000
--- a/app/code/Magento/Theme/Observer/ThemeRegistrationObserver.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-namespace Magento\Theme\Observer;
-
-use Magento\Framework\Event\Observer as EventObserver;
-use Magento\Framework\Event\ObserverInterface;
-use Magento\Theme\Model\Theme;
-
-class ThemeRegistrationObserver implements ObserverInterface
-{
-    /**
-     * @var \Magento\Theme\Model\Theme\Registration
-     */
-    protected $registration;
-
-    /**
-     * @var \Psr\Log\LoggerInterface
-     */
-    protected $logger;
-
-    /**
-     * @param Theme\Registration $registration
-     * @param \Psr\Log\LoggerInterface $logger
-     */
-    public function __construct(
-        \Magento\Theme\Model\Theme\Registration $registration,
-        \Psr\Log\LoggerInterface $logger
-    ) {
-        $this->registration = $registration;
-        $this->logger = $logger;
-    }
-
-    /**
-     * Theme registration
-     *
-     * @param \Magento\Framework\Event\Observer $observer
-     * @return $this
-     */
-    public function execute(\Magento\Framework\Event\Observer $observer)
-    {
-        $pathPattern = $observer->getEvent()->getPathPattern();
-        try {
-            $this->registration->register($pathPattern);
-        } catch (\Magento\Framework\Exception\LocalizedException $e) {
-            $this->logger->critical($e);
-        }
-        return $this;
-    }
-}
diff --git a/app/code/Magento/Theme/Setup/InstallData.php b/app/code/Magento/Theme/Setup/InstallData.php
deleted file mode 100644
index 32503c78fc70f353c5f74a7aeddce6536fc05e37..0000000000000000000000000000000000000000
--- a/app/code/Magento/Theme/Setup/InstallData.php
+++ /dev/null
@@ -1,111 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-namespace Magento\Theme\Setup;
-
-use Magento\Framework\Setup\InstallDataInterface;
-use Magento\Framework\Setup\ModuleContextInterface;
-use Magento\Framework\Setup\ModuleDataSetupInterface;
-
-/**
- * @codeCoverageIgnore
- */
-class InstallData implements InstallDataInterface
-{
-    /**
-     * Theme resource factory
-     *
-     * @var \Magento\Theme\Model\ResourceModel\Theme\CollectionFactory
-     */
-    private $themeResourceFactory;
-
-    /**
-     * Theme collection factory
-     *
-     * @var \Magento\Theme\Model\Theme\CollectionFactory
-     */
-    private $themeFactory;
-
-    /**
-     * Init
-     *
-     * @param \Magento\Theme\Model\ResourceModel\Theme\CollectionFactory $themeResourceFactory
-     * @param \Magento\Theme\Model\Theme\CollectionFactory $themeFactory
-     */
-    public function __construct(
-        \Magento\Theme\Model\ResourceModel\Theme\CollectionFactory $themeResourceFactory,
-        \Magento\Theme\Model\Theme\CollectionFactory $themeFactory
-    ) {
-        $this->themeResourceFactory = $themeResourceFactory;
-        $this->themeFactory = $themeFactory;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
-    {
-        /*
-         * Register themes
-         */
-        $setup->getEventManager()->dispatch('theme_registration_from_filesystem');
-
-        /**
-         * Update theme's data
-         */
-        $fileCollection = $this->createTheme();
-        $fileCollection->setItemObjectClass('Magento\Theme\Model\Theme\Data');
-
-        $resourceCollection = $this->createThemeResource();
-        $resourceCollection->setItemObjectClass('Magento\Theme\Model\Theme\Data');
-
-        /** @var $theme \Magento\Framework\View\Design\ThemeInterface */
-        foreach ($resourceCollection as $theme) {
-            $themeType = $fileCollection->hasTheme($theme)
-                ? \Magento\Framework\View\Design\ThemeInterface::TYPE_PHYSICAL
-                : \Magento\Framework\View\Design\ThemeInterface::TYPE_VIRTUAL;
-            $theme->setType($themeType)->save();
-        }
-
-        $fileCollection = $this->createTheme();
-        $fileCollection->setItemObjectClass('Magento\Theme\Model\Theme\Data');
-
-        $themeDbCollection = $this->createThemeResource();
-        $themeDbCollection->setItemObjectClass('Magento\Theme\Model\Theme\Data');
-
-        /** @var $theme \Magento\Framework\View\Design\ThemeInterface */
-        foreach ($fileCollection as $theme) {
-            $dbTheme = $themeDbCollection->getThemeByFullPath($theme->getFullPath());
-            $dbTheme->setCode($theme->getCode());
-            $dbTheme->save();
-        }
-
-        /**
-         * Update rows in theme
-         */
-        $setup->getConnection()->update(
-            $setup->getTable('theme'),
-            ['area' => 'frontend'],
-            ['area = ?' => '']
-        );
-    }
-
-    /**
-     * @return \Magento\Theme\Model\ResourceModel\Theme\Collection
-     */
-    public function createThemeResource()
-    {
-        return $this->themeResourceFactory->create();
-    }
-
-    /**
-     * @return \Magento\Theme\Model\Theme\Collection
-     */
-    public function createTheme()
-    {
-        return $this->themeFactory->create();
-    }
-}
diff --git a/app/code/Magento/Theme/Setup/RecurringData.php b/app/code/Magento/Theme/Setup/RecurringData.php
new file mode 100644
index 0000000000000000000000000000000000000000..309e62ab09b9a868cac2f78cd4597a7ef3290525
--- /dev/null
+++ b/app/code/Magento/Theme/Setup/RecurringData.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Theme\Setup;
+
+use Magento\Framework\Setup\InstallDataInterface;
+use Magento\Framework\Setup\ModuleContextInterface;
+use Magento\Framework\Setup\ModuleDataSetupInterface;
+use Magento\Theme\Model\Theme\Registration;
+
+/**
+ * Upgrade registered themes
+ */
+class RecurringData implements InstallDataInterface
+{
+    /**
+     * Theme registration
+     *
+     * @var Registration
+     */
+    private $themeRegistration;
+
+    /**
+     * Init
+     *
+     * @param Registration $themeRegistration
+     */
+    public function __construct(Registration $themeRegistration)
+    {
+        $this->themeRegistration = $themeRegistration;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
+    {
+        $this->themeRegistration->register();
+    }
+}
diff --git a/app/code/Magento/Theme/Test/Unit/Observer/ThemeRegistrationObserverTest.php b/app/code/Magento/Theme/Test/Unit/Observer/ThemeRegistrationObserverTest.php
deleted file mode 100644
index b27f8cede5c2d7a6040b77f8dd6546ec6542af73..0000000000000000000000000000000000000000
--- a/app/code/Magento/Theme/Test/Unit/Observer/ThemeRegistrationObserverTest.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-namespace Magento\Theme\Test\Unit\Observer;
-
-class ThemeRegistrationObserverTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $logger;
-
-    /**
-     * @var \Magento\Theme\Model\Theme\Registration|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $registration;
-
-    /**
-     * @var \Magento\Theme\Observer\ThemeRegistrationObserver
-     */
-    protected $themeObserver;
-
-    protected function setUp()
-    {
-        $this->registration = $this->getMockBuilder('Magento\Theme\Model\Theme\Registration')
-            ->disableOriginalConstructor()
-            ->getMock();
-        $this->logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
-
-        $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
-        $this->themeObserver = $objectManagerHelper->getObject(
-            'Magento\Theme\Observer\ThemeRegistrationObserver',
-            [
-                'registration' => $this->registration,
-                'logger' => $this->logger,
-            ]
-        );
-    }
-
-    public function testThemeRegistration()
-    {
-        $pattern = 'some pattern';
-        $eventMock = $this->getMockBuilder('Magento\Framework\Event')
-            ->setMethods(['getPathPattern'])
-            ->disableOriginalConstructor()
-            ->getMock();
-        $eventMock->expects($this->any())->method('getPathPattern')->willReturn($pattern);
-        $observerMock = $this->getMockBuilder('Magento\Framework\Event\Observer')
-            ->disableOriginalConstructor()
-            ->getMock();
-        $observerMock->expects($this->any())->method('getEvent')->willReturn($eventMock);
-        $this->registration->expects($this->once())
-            ->method('register')
-            ->with($pattern)
-            ->willThrowException(new \Magento\Framework\Exception\LocalizedException(__('exception')));
-        $this->logger->expects($this->once())
-            ->method('critical');
-
-        /** @var $observerMock \Magento\Framework\Event\Observer */
-        $this->themeObserver->execute($observerMock);
-    }
-}
diff --git a/app/code/Magento/Theme/etc/events.xml b/app/code/Magento/Theme/etc/events.xml
index 2f6155eeade189bad071d27a50cfa808f2244c1d..709f64eaf91ae50fc4b696b5494e8e13712eb44a 100644
--- a/app/code/Magento/Theme/etc/events.xml
+++ b/app/code/Magento/Theme/etc/events.xml
@@ -12,8 +12,4 @@
     <event name="theme_save_after">
         <observer name="check_theme_is_assigned" instance="Magento\Theme\Observer\CheckThemeIsAssignedObserver" />
     </event>
-    <event name="theme_registration_from_filesystem">
-        <observer name="theme_registration_observer" instance="Magento\Theme\Observer\ThemeRegistrationObserver"
-                  />
-    </event>
 </config>
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/WebApiApplication.php b/dev/tests/api-functional/framework/Magento/TestFramework/WebApiApplication.php
index 56936fa716784c7ea003afd93e87ab31da048817..c7414d717eb270857d3b2ea292eb8bb0c27d689e 100644
--- a/dev/tests/api-functional/framework/Magento/TestFramework/WebApiApplication.php
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/WebApiApplication.php
@@ -33,7 +33,7 @@ class WebApiApplication extends Application
 
         /* Install application */
         if ($installOptions) {
-            $installCmd = 'php -f ' . BP . '/bin/magento setup:install';
+            $installCmd = 'php -f ' . BP . '/bin/magento setup:install -vvv';
             $installArgs = [];
             foreach ($installOptions as $optionName => $optionValue) {
                 if (is_bool($optionValue)) {
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Page/Header.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Page/Header.php
index cbe0c75b7d923176473dc55456345d4fee719b1f..21d8d2e3735f4cca250d21b9fb06c9b7e7d16fc7 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Page/Header.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Page/Header.php
@@ -85,4 +85,28 @@ class Header extends Block
         $search = $this->_rootElement->find($this->searchSelector, Locator::SELECTOR_CSS, 'globalsearch');
         return $search->isExistValueInSearchResult($query);
     }
+
+    /**
+     * Is admin search preview visible in suggestion dropdown.
+     *
+     * @param string $query
+     * @param string $type
+     * @return bool
+     */
+    public function isAdminSearchPreviewVisible($query, $type)
+    {
+        /** @var GlobalsearchElement $search */
+        $search = $this->_rootElement->find('searchPreview' . $type, Locator::SELECTOR_ID);
+        return $search->getText() === $query;
+    }
+
+    /**
+     * Navigate to grid of specified type
+     *
+     * @param string $type
+     */
+    public function navigateToGrid($type)
+    {
+        $this->_rootElement->find('searchPreview' . $type, Locator::SELECTOR_ID)->click();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertGlobalSearchCustomerName.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertGlobalSearchCustomerName.php
index 6ab4e17f0f8e58df9f527d9d81f7d7abd015e76a..2fcf933a4567b42d1c9616edb08faa99effafd2b 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertGlobalSearchCustomerName.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertGlobalSearchCustomerName.php
@@ -8,6 +8,7 @@ namespace Magento\Backend\Test\Constraint;
 
 use Magento\Backend\Test\Fixture\GlobalSearch;
 use Magento\Backend\Test\Page\Adminhtml\Dashboard;
+use Magento\Customer\Test\Page\Adminhtml\CustomerIndex;
 use Magento\Mtf\Constraint\AbstractConstraint;
 
 /**
@@ -21,9 +22,10 @@ class AssertGlobalSearchCustomerName extends AbstractConstraint
      *
      * @param Dashboard $dashboard
      * @param GlobalSearch $search
+     * @param CustomerIndex $customerIndex
      * @return void
      */
-    public function processAssert(Dashboard $dashboard, GlobalSearch $search)
+    public function processAssert(Dashboard $dashboard, GlobalSearch $search, CustomerIndex $customerIndex)
     {
         $customer = $search->getDataFieldConfig('query')['source']->getEntity();
         $customerName = $customer->getFirstname() . " " . $customer->getLastname();
@@ -32,6 +34,19 @@ class AssertGlobalSearchCustomerName extends AbstractConstraint
             $isVisibleInResult,
             'Customer name ' . $customerName . ' is absent in search results'
         );
+
+        $dashboard->getAdminPanelHeader()->navigateToGrid("Customers");
+        $isCustomerGridVisible = $customerIndex->getCustomerGridBlock()->isVisible();
+        \PHPUnit_Framework_Assert::assertTrue(
+            $isCustomerGridVisible,
+            'Customer grid is not visible'
+        );
+        \PHPUnit_Framework_Assert::assertContains(
+            (string) $customer->getId(),
+            $customerIndex->getCustomerGridBlock()->getAllIds(),
+            'Customer grid does not have ' . $customerName . ' in search results'
+        );
+
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertGlobalSearchOrderId.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertGlobalSearchOrderId.php
index ed988ab79a3303de4646ade7b952cd485d1626ed..5d6fac04237fc25231ff8340458064e2cb17bc67 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertGlobalSearchOrderId.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertGlobalSearchOrderId.php
@@ -9,6 +9,7 @@ namespace Magento\Backend\Test\Constraint;
 use Magento\Backend\Test\Fixture\GlobalSearch;
 use Magento\Backend\Test\Page\Adminhtml\Dashboard;
 use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Sales\Test\Page\Adminhtml\OrderIndex;
 
 /**
  * Class AssertGlobalSearchOrderId
@@ -21,9 +22,10 @@ class AssertGlobalSearchOrderId extends AbstractConstraint
      *
      * @param Dashboard $dashboard
      * @param GlobalSearch $search
+     * @param OrderIndex $orderIndex
      * @return void
      */
-    public function processAssert(Dashboard $dashboard, GlobalSearch $search)
+    public function processAssert(Dashboard $dashboard, GlobalSearch $search, OrderIndex $orderIndex)
     {
         $order = $search->getDataFieldConfig('query')['source']->getEntity();
         $orderId = "Order #" . $order->getId();
@@ -32,6 +34,19 @@ class AssertGlobalSearchOrderId extends AbstractConstraint
             $isVisibleInResult,
             'Order Id ' . $order->getId() . ' is absent in search results'
         );
+
+        $dashboard->getAdminPanelHeader()->navigateToGrid("Orders");
+        $isOrderGridVisible = $orderIndex->getSalesOrderGrid()->isVisible();
+
+        \PHPUnit_Framework_Assert::assertTrue(
+            $isOrderGridVisible,
+            'Order grid is not visible'
+        );
+        \PHPUnit_Framework_Assert::assertContains(
+            (string) $order->getId(),
+            $orderIndex->getSalesOrderGrid()->getAllIds(),
+            'Order grid does not have ' . $order->getId()  . ' in search results'
+        );
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertGlobalSearchPreview.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertGlobalSearchPreview.php
new file mode 100644
index 0000000000000000000000000000000000000000..890eee983083db3b48054dec9030ec8269f2b5a2
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertGlobalSearchPreview.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Backend\Test\Constraint;
+
+use Magento\Backend\Test\Fixture\GlobalSearch;
+use Magento\Backend\Test\Page\Adminhtml\Dashboard;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Class AssertGlobalSearchPreview
+ * Assert that admin search preview is present in search results
+ */
+class AssertGlobalSearchPreview extends AbstractConstraint
+{
+    /**
+     * Assert that admin search preview is present in search results
+     *
+     * @param Dashboard $dashboard
+     * @param GlobalSearch $search
+     * @return void
+     */
+    public function processAssert(Dashboard $dashboard, GlobalSearch $search)
+    {
+        $types = ['Products', 'Customers', 'Orders', 'Pages'];
+        foreach ($types as $type) {
+            $this->adminSearchAssert($dashboard, $search, $type);
+        }
+    }
+
+    /**
+     * Assert value of item in admin search preview
+     *
+     * @param Dashboard $dashboard
+     * @param GlobalSearch $search
+     * @param string $type
+     */
+    private function adminSearchAssert($dashboard, $search, $type)
+    {
+        $adminSearchPreview = '"' . $search->getQuery() . '" in '. $type;
+        $isVisibleInResult = $dashboard->getAdminPanelHeader()->isAdminSearchPreviewVisible($adminSearchPreview, $type);
+        \PHPUnit_Framework_Assert::assertTrue(
+            $isVisibleInResult,
+            'Search Preview for ' . $type . ' is not in search results'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Search preview is present in search results';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/GlobalSearchEntityTest.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/GlobalSearchEntityTest.xml
index c4341095b42b3eed2e6a68aeefc40d671499c364..87eccf18b69b5ea50c9bed1b314305d80dcf6b34 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/GlobalSearchEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/GlobalSearchEntityTest.xml
@@ -7,6 +7,11 @@
  -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
     <testCase name="Magento\Backend\Test\TestCase\GlobalSearchEntityTest" summary="Global Search Backend " ticketId="MAGETWO-28457">
+        <variation name="GlobalSearchEntityTestVariation1">
+            <data name="description" xsi:type="string">search shows admin preview</data>
+            <data name="search/data/query" xsi:type="string">Some search term</data>
+            <constraint name="Magento\Backend\Test\Constraint\AssertGlobalSearchPreview" />
+        </variation>
         <variation name="GlobalSearchEntityTestVariation2">
             <data name="description" xsi:type="string">search with 2 sign return no results</data>
             <data name="search/data/query" xsi:type="string">:)</data>
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/Block/Adminhtml/Block/Edit/SynonymGroupForm.php b/dev/tests/functional/tests/app/Magento/Search/Test/Block/Adminhtml/Block/Edit/SynonymGroupForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..000fd9895e821be57340082ce203a18a55d4429e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/Block/Adminhtml/Block/Edit/SynonymGroupForm.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Search\Test\Block\Adminhtml\Block\Edit;
+
+use Magento\Mtf\Block\Form;
+use Magento\Mtf\Client\Element\SimpleElement;
+use Magento\Mtf\Fixture\FixtureInterface;
+
+/**
+ * Form for Synonym Group creation.
+ */
+class SynonymGroupForm extends Form
+{
+    /**
+     * Content Editor toggle button id.
+     *
+     * @var string
+     */
+    protected $toggleButton = "#toggleblock_content";
+
+    /**
+     * Synonym Group Content area.
+     *
+     * @var string
+     */
+    protected $contentForm = '[name="content"]';
+
+    /**
+     * Fill the page form.
+     *
+     * @param FixtureInterface $fixture
+     * @param SimpleElement $element
+     * @return $this
+     */
+    public function fill(FixtureInterface $fixture, SimpleElement $element = null)
+    {
+        return parent::fill($fixture, $element);
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/Block/Adminhtml/Block/Edit/SynonymGroupForm.xml b/dev/tests/functional/tests/app/Magento/Search/Test/Block/Adminhtml/Block/Edit/SynonymGroupForm.xml
new file mode 100644
index 0000000000000000000000000000000000000000..761af98e1918e4383fbe8718682e6dc0c539fbd5
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/Block/Adminhtml/Block/Edit/SynonymGroupForm.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <scope_id>
+            <selector>[name="scope_id"]</selector>
+            <input>selectstore</input>
+        </scope_id>
+        <mergeOnConflict>
+            <input>checkbox</input>
+        </mergeOnConflict>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/Block/Adminhtml/Block/SynonymGroupGrid.php b/dev/tests/functional/tests/app/Magento/Search/Test/Block/Adminhtml/Block/SynonymGroupGrid.php
new file mode 100644
index 0000000000000000000000000000000000000000..1a1bc5732d9fe460c61422e5cd546b9e076e5117
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/Block/Adminhtml/Block/SynonymGroupGrid.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Search\Test\Block\Adminhtml\Block;
+
+use Magento\Mtf\Client\Element\SimpleElement;
+use Magento\Ui\Test\Block\Adminhtml\DataGrid;
+
+/**
+ * Backend Data Grid for managing "SynonymGroup" entities.
+ */
+class SynonymGroupGrid extends DataGrid
+{
+    /**
+     * Select action toggle.
+     *
+     * @var string
+     */
+    protected $selectAction = '.action-select';
+
+    /**
+     * Filters array mapping.
+     *
+     * @var array
+     */
+    protected $filters = [
+        'synonyms' => [
+            'selector' => '[name="synonyms"]',
+        ],
+        'scope_id' => [
+            'selector' => '[name="scope_id"]',
+            'input' => 'simplifiedselect'
+        ],
+    ];
+
+    /**
+     * Click on "Edit" link.
+     *
+     * @param SimpleElement $rowItem
+     * @return void
+     */
+    protected function clickEditLink(SimpleElement $rowItem)
+    {
+        $rowItem->find($this->selectAction)->click();
+        $rowItem->find($this->editLink)->click();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/Constraint/AssertSynonymGroupDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Search/Test/Constraint/AssertSynonymGroupDeleteMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..b445887cf411bceb615ddf3b5c953fd47ec98eed
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/Constraint/AssertSynonymGroupDeleteMessage.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Search\Test\Constraint;
+
+use Magento\Search\Test\Page\Adminhtml\SynonymGroupIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that after delete synonym group successful delete message appears.
+ */
+class AssertSynonymGroupDeleteMessage extends AbstractConstraint
+{
+    const DELETE_MESSAGE = 'The synonym group has been deleted.';
+
+    /**
+     * Assert that after delete Synonym Group successful delete message appears.
+     *
+     * @param SynonymGroupIndex $synonymGroupIndex
+     * @return void
+     */
+    public function processAssert(SynonymGroupIndex $synonymGroupIndex)
+    {
+        $actualMessage = $synonymGroupIndex->getMessagesBlock()->getSuccessMessage();
+        \PHPUnit_Framework_Assert::assertEquals(
+            self::DELETE_MESSAGE,
+            $actualMessage,
+            'Wrong success message is displayed.'
+            . "\nExpected: " . self::DELETE_MESSAGE
+            . "\nActual: " . $actualMessage
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Synonym Group success delete message is present.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/Constraint/AssertSynonymGroupInGrid.php b/dev/tests/functional/tests/app/Magento/Search/Test/Constraint/AssertSynonymGroupInGrid.php
new file mode 100644
index 0000000000000000000000000000000000000000..642b366830e095f8c129887cddf90b52cbd49507
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/Constraint/AssertSynonymGroupInGrid.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Search\Test\Constraint;
+
+use Magento\Search\Test\Fixture\SynonymGroup;
+use Magento\Search\Test\Page\Adminhtml\SynonymGroupIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that created Synonym Group can be found in grid.
+ */
+class AssertSynonymGroupInGrid extends AbstractConstraint
+{
+    /**
+     * Assert that created Synonym Group can be found in grid via: synonyms.
+     *
+     * @param SynonymGroup $synonymGroup
+     * @param SynonymGroupIndex $synonymGroupIndex
+     * @return void
+     *
+     */
+    public function processAssert(SynonymGroup $synonymGroup, SynonymGroupIndex $synonymGroupIndex)
+    {
+        $synonymGroupIndex->open();
+        $data = $synonymGroup->getData();
+        $filter = [
+            'synonyms' => $data['synonyms'],
+        ];
+
+        $synonymGroupIndex->getSynonymGroupGrid()->search($filter);
+
+        \PHPUnit_Framework_Assert::assertTrue(
+            $synonymGroupIndex->getSynonymGroupGrid()->isRowVisible($filter, false, false),
+            'Synonym Group with '
+            . 'synonyms \'' . $filter['synonyms'] . '\', '
+            . 'is absent in Synonym grid.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Synonym Group is present in grid.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/Constraint/AssertSynonymGroupSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Search/Test/Constraint/AssertSynonymGroupSuccessSaveMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..b2102d2ae6050e90472d27e3c00bc77e3cae590d
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/Constraint/AssertSynonymGroupSuccessSaveMessage.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Search\Test\Constraint;
+
+use Magento\Search\Test\Page\Adminhtml\SynonymGroupIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that after save block successful message appears.
+ */
+class AssertSynonymGroupSuccessSaveMessage extends AbstractConstraint
+{
+    const SUCCESS_SAVE_MESSAGE = 'You saved the synonym group.';
+
+    /**
+     * Assert that after save Synonym Group successful message appears.
+     *
+     * @param SynonymGroupIndex $synonymGroupIndex
+     * @return void
+     */
+    public function processAssert(SynonymGroupIndex $synonymGroupIndex)
+    {
+        $actualMessage = $synonymGroupIndex->getMessagesBlock()->getSuccessMessage();
+        \PHPUnit_Framework_Assert::assertEquals(
+            self::SUCCESS_SAVE_MESSAGE,
+            $actualMessage,
+            'Wrong success message is displayed.'
+            . "\nExpected: " . self::SUCCESS_SAVE_MESSAGE
+            . "\nActual: " . $actualMessage
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Synonym Group success create message is present.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/Constraint/AssertSynonymMergeErrorMessage.php b/dev/tests/functional/tests/app/Magento/Search/Test/Constraint/AssertSynonymMergeErrorMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..b953caffe3914845d17a6b0c085a358dcd75a4e0
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/Constraint/AssertSynonymMergeErrorMessage.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Search\Test\Constraint;
+
+use Magento\Search\Test\Page\Adminhtml\SynonymGroupNew;
+use Magento\Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that after save block successful message appears.
+ */
+class AssertSynonymMergeErrorMessage extends AbstractConstraint
+{
+    const ERROR_MESSAGE = 'The terms you entered';
+
+    /**
+     * Assert that after save Synonym Group successful message appears.
+     *
+     * @param SynonymGroupNew $synonymGroupNew
+     * @return void
+     */
+    public function processAssert(SynonymGroupNew $synonymGroupNew)
+    {
+        $actualMessage = $synonymGroupNew->getMessagesBlock()->getErrorMessage();
+        \PHPUnit_Framework_Assert::assertContains(
+            self::ERROR_MESSAGE,
+            $actualMessage,
+            'Wrong success message is displayed.'
+            . "\nExpected: " . self::ERROR_MESSAGE
+            . "\nActual: " . $actualMessage
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Synonym Group error message is present.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/Fixture/SynonymGroup.xml b/dev/tests/functional/tests/app/Magento/Search/Test/Fixture/SynonymGroup.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7cc67f87b3d6639902a4fbc97a524edb29350aa4
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/Fixture/SynonymGroup.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
+    <fixture name="synonymGroup"
+             module="Magento_Search"
+             type="flat"
+             entity_type="synonym_group"
+             collection="Magento\Search\Model\ResourceModel\Block\Grid\Collection"
+             handler_interface="Magento\Search\Test\Handler\SynonymGroup\SynonymGroupInterface"
+             repository_class="Magento\Search\Test\Repository\SynonymGroup" class="Magento\Search\Test\Fixture\SynonymGroup">
+        <field name="group_id" is_required="1 "/>
+        <field name="synonyms" is_required="0" />
+        <field name="scope_id" is_required="0" source="Magento\Search\Test\Fixture\SynonymGroup\ScopeId" />
+        <field name="mergeOnConflict" is_required="0" />
+    </fixture>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/Fixture/SynonymGroup/ScopeId.php b/dev/tests/functional/tests/app/Magento/Search/Test/Fixture/SynonymGroup/ScopeId.php
new file mode 100644
index 0000000000000000000000000000000000000000..5dd92e9774a6de93be45d3db8a6a5cfa55ce3770
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/Fixture/SynonymGroup/ScopeId.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Search\Test\Fixture\SynonymGroup;
+
+use Magento\Store\Test\Fixture\Store;
+use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Mtf\Fixture\DataSource;
+
+/**
+ * Class ScopeId
+ */
+class ScopeId extends DataSource
+{
+    /**
+     * Return store.
+     *
+     * @var Store
+     */
+    protected $store = null;
+
+    /**
+     * @constructor
+     * @param FixtureFactory $fixtureFactory
+     * @param array $params
+     * @param array $data
+     */
+    public function __construct(FixtureFactory $fixtureFactory, array $params, array $data = [])
+    {
+        $this->params = $params;
+        if (isset($data['dataset'])) {
+            $store = $fixtureFactory->createByCode('store', ['dataset' => $data['dataset']]);
+            if (!$store->hasData('store_id')) {
+                $store->persist();
+            }
+            $this->store = $store;
+            $this->data = $store->getName();
+        } else {
+            $this->data = null;
+        }
+    }
+
+    /**
+     * Return store.
+     *
+     * @return Store
+     */
+    public function getStore()
+    {
+        return $this->store;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/Handler/SynonymGroup/Curl.php b/dev/tests/functional/tests/app/Magento/Search/Test/Handler/SynonymGroup/Curl.php
new file mode 100644
index 0000000000000000000000000000000000000000..1e56a656783792336c3ec46b1f5e6558fadbf0b8
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/Handler/SynonymGroup/Curl.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Search\Test\Handler\SynonymGroup;
+
+use Magento\Mtf\Fixture\FixtureInterface;
+use Magento\Mtf\Handler\Curl as AbstractCurl;
+use Magento\Mtf\Util\Protocol\CurlTransport;
+use Magento\Mtf\Util\Protocol\CurlTransport\BackendDecorator;
+
+/**
+ * Curl handler for creating Synonym Group.
+ */
+class Curl extends AbstractCurl implements SynonymGroupInterface
+{
+    /**
+     * Url for saving data.
+     *
+     * @var string
+     */
+    protected $saveUrl = 'search/synonyms/save/';
+
+    /**
+     * Mapping values for data.
+     *
+     * @var array
+     */
+    protected $mappingData = [
+        'mergeOnConflict' => [
+            'Yes' => 1,
+            'No' => 0,
+        ],
+        'scope_id' => [
+            'All Websites' => '0:0',
+            'All Store Views' => '1:0',
+            'Default Store View' => '1:1',
+        ],
+    ];
+
+    /**
+     * POST request for creating Synonym Group.
+     *
+     * @param FixtureInterface|null $fixture [optional]
+     * @return array
+     * @throws \Exception
+     */
+    public function persist(FixtureInterface $fixture = null)
+    {
+        $data = $this->replaceMappingData($fixture->getData());
+
+        $url = $_ENV['app_backend_url'] . $this->saveUrl;
+        $curl = new BackendDecorator(new CurlTransport(), $this->_configuration);
+        $curl->write($url, $data);
+        $response = $curl->read();
+        $curl->close();
+        if (!strpos($response, 'data-ui-id="messages-message-success"')) {
+            throw new \Exception(
+                "Synonym Group entity creation by curl handler was not successful! Response: $response"
+            );
+        }
+
+        preg_match("`group_id\/(\d*?)\/`", $response, $matches);
+        $id = isset($matches[1]) ? $matches[1] : null;
+
+        return ['group_id' => $id];
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/Handler/SynonymGroup/SynonymGroupInterface.php b/dev/tests/functional/tests/app/Magento/Search/Test/Handler/SynonymGroup/SynonymGroupInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..3681f06378633191285f6b66fc6ae90be7289ba0
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/Handler/SynonymGroup/SynonymGroupInterface.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Search\Test\Handler\SynonymGroup;
+
+use Magento\Mtf\Handler\HandlerInterface;
+
+/**
+ * Interface SynonymGroupInterface
+ */
+interface SynonymGroupInterface extends HandlerInterface
+{
+    //
+}
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/Page/Adminhtml/SynonymGroupIndex.xml b/dev/tests/functional/tests/app/Magento/Search/Test/Page/Adminhtml/SynonymGroupIndex.xml
new file mode 100644
index 0000000000000000000000000000000000000000..03bf60bdd17c1b539e2e81fa88be467dc5ac3cf6
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/Page/Adminhtml/SynonymGroupIndex.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/pages.xsd">
+    <page name="synonymGroupIndex" area="Adminhtml" mca="search/synonyms/index" module="Magento_Search">
+        <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator=".messages .message" strategy="css selector" />
+        <block name="gridPageActions" class="Magento\Backend\Test\Block\GridPageActions" locator=".page-main-actions" strategy="css selector" />
+        <block name="synonymGroupGrid" class="Magento\Search\Test\Block\Adminhtml\Block\SynonymGroupGrid" locator=".admin__data-grid-outer-wrap" strategy="css selector" />
+    </page>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/Page/Adminhtml/SynonymGroupNew.xml b/dev/tests/functional/tests/app/Magento/Search/Test/Page/Adminhtml/SynonymGroupNew.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bac3cb7422f69b31f8dff74ca78ed1d386eb4276
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/Page/Adminhtml/SynonymGroupNew.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/pages.xsd">
+    <page name="synonymGroupNew" area="Adminhtml" mca="search/synonyms/new" module="Magento_Search">
+        <block name="formPageActions" class="Magento\Backend\Test\Block\FormPageActions" locator=".page-main-actions" strategy="css selector" />
+        <block name="synonymGroupForm" class="Magento\Search\Test\Block\Adminhtml\Block\Edit\SynonymGroupForm" locator="[id='page:main-container']" strategy="css selector" />
+        <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator="#messages" strategy="css selector" />
+        <block name="modalBlock" class="Magento\Ui\Test\Block\Adminhtml\Modal" locator="._show[data-role=modal]" strategy="css selector"/>
+    </page>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/Repository/SynonymGroup.xml b/dev/tests/functional/tests/app/Magento/Search/Test/Repository/SynonymGroup.xml
new file mode 100644
index 0000000000000000000000000000000000000000..347d364d57a032df9f91bd6125d1e4fd7a10fb34
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/Repository/SynonymGroup.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/Magento/Mtf/Repository/etc/repository.xsd">
+    <repository class="Magento\Search\Test\Repository\SynonymGroup">
+        <dataset name="prepareMerge">
+            <field name="scope_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default_store_view</item>
+            </field>
+            <field name="synonyms" xsi:type="string">test_synonym_%isolation%,test_synonym_2_test_synonym_%isolation%</field>
+            <field name="mergeOnConflict" xsi:type="string">Yes</field>
+        </dataset>
+    </repository>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/CreateSynonymGroupEntityTest.php b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/CreateSynonymGroupEntityTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..bba88a54b5e8991da23641bb821ca6c3b819f931
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/CreateSynonymGroupEntityTest.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Search\Test\TestCase;
+
+use Magento\Search\Test\Page\Adminhtml\SynonymGroupIndex;
+use Magento\Search\Test\Page\Adminhtml\SynonymGroupNew;
+use Magento\Mtf\TestCase\Injectable;
+use Magento\Search\Test\Fixture\SynonymGroup;
+
+/**
+ * Preconditions:
+ * 1. Create store view.
+ *
+ * Steps:
+ * 1. Open Backend.
+ * 2. Go to Marketing > Search Synonyms.
+ * 3. Click "New Synonym Group" button.
+ * 4. Fill data according to dataset.
+ * 5. Perform all assertions.
+ *
+ * @group Search_(MX)
+ * @ZephyrId MAGETWO-47681
+ */
+class CreateSynonymGroupEntityTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    const DOMAIN = 'MX';
+    const TEST_TYPE = 'extended_acceptance_test';
+    /* end tags */
+
+    /**
+     * Page Index.
+     *
+     * @var synonymGroupIndex
+     */
+    protected $synonymGroupIndex;
+
+    /**
+     * Page synonymGroupNew.
+     *
+     * @var SynonymGroupNew
+     */
+    protected $synonymGroupNew;
+
+    /**
+     * Injection data.
+     *
+     * @param SynonymGroupIndex $synonymGroupIndex
+     * @param SynonymGroupNew $synonymGroupNew
+     * @return void
+     */
+    public function __inject(
+        SynonymGroupIndex $synonymGroupIndex,
+        SynonymGroupNew $synonymGroupNew
+    ) {
+        $this->synonymGroupIndex = $synonymGroupIndex;
+        $this->synonymGroupNew = $synonymGroupNew;
+    }
+
+    /**
+     * Create Synonym Group.
+     *
+     * @param SynonymGroup $synonymGroup
+     * @return void
+     */
+    public function test(SynonymGroup $synonymGroup)
+    {
+        // Steps
+        $this->synonymGroupIndex->open();
+        $this->synonymGroupIndex->getGridPageActions()->addNew();
+        $this->synonymGroupNew->getSynonymGroupForm()->fill($synonymGroup);
+        $this->synonymGroupNew->getFormPageActions()->save();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/CreateSynonymGroupEntityTest.xml b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/CreateSynonymGroupEntityTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..557a64118d5a22ac4d1ffa14a422e78c8b60fff9
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/CreateSynonymGroupEntityTest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\Search\Test\TestCase\CreateSynonymGroupEntityTest" summary="Create Synonym Group" ticketId="MAGETWO-47681">
+        <variation name="CreateSynonymGroupEntityTestVariation1">
+            <data name="tag" xsi:type="string">test_type:extended_acceptance_test</data>
+            <data name="synonymGroup/data/synonyms" xsi:type="string">synonym_%isolation%</data>
+            <constraint name="Magento\Search\Test\Constraint\AssertSynonymGroupSuccessSaveMessage" />
+            <constraint name="Magento\Search\Test\Constraint\AssertSynonymGroupInGrid" />
+        </variation>
+    </testCase>
+    <testCase name="Magento\Search\Test\TestCase\CreateSynonymGroupEntityTest" summary="Create Synonym Group with few synonyms and Default Store View" ticketId="MAGETWO-47681">
+        <variation name="CreateSynonymGroupEntityTestVariation2">
+            <data name="tag" xsi:type="string">test_type:extended_acceptance_test</data>
+            <data name="synonymGroup/data/synonyms" xsi:type="string">shoes_%isolation%,foot wear_%isolation%,mens shoes_%isolation%,women shoes_%isolation%</data>
+            <data name="synonymGroup/data/scope_id/dataset" xsi:type="string">default_store_view</data>
+            <constraint name="Magento\Search\Test\Constraint\AssertSynonymGroupSuccessSaveMessage" />
+            <constraint name="Magento\Search\Test\Constraint\AssertSynonymGroupInGrid" />
+        </variation>
+    </testCase>
+    <testCase name="Magento\Search\Test\TestCase\CreateSynonymGroupEntityTest" summary="Create Synonym Group with custom Website and Store View" ticketId="MAGETWO-47681">
+        <variation name="CreateSynonymGroupEntityTestVariation3">
+            <data name="tag" xsi:type="string">test_type:extended_acceptance_test</data>
+            <data name="synonymGroup/data/synonyms" xsi:type="string">synonym_%isolation%</data>
+            <data name="synonymGroup/data/scope_id/dataset" xsi:type="string">custom_store</data>
+            <constraint name="Magento\Search\Test\Constraint\AssertSynonymGroupSuccessSaveMessage" />
+            <constraint name="Magento\Search\Test\Constraint\AssertSynonymGroupInGrid" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/DeleteSynonymGroupEntityTest.php b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/DeleteSynonymGroupEntityTest.php
new file mode 100755
index 0000000000000000000000000000000000000000..2ae9974a39e74a618abcc853ed594e06b2390851
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/DeleteSynonymGroupEntityTest.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Search\Test\TestCase;
+
+use Magento\Search\Test\Page\Adminhtml\SynonymGroupIndex;
+use Magento\Search\Test\Page\Adminhtml\SynonymGroupNew;
+use Magento\Mtf\TestCase\Injectable;
+use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Search\Test\Fixture\SynonymGroup;
+
+/**
+ * Preconditions:
+ * 1. Create Synonym Group view.
+ *
+ * Steps:
+ * 1. Open Backend.
+ * 2. Go to Marketing > Search Synonyms.
+ * 3. Delete created Synonym Group
+ * 4. Perform all assertions.
+ *
+ * @group Search_(MX)
+ * @ZephyrId MAGETWO-47683
+ */
+class DeleteSynonymGroupEntityTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    const DOMAIN = 'MX';
+    const TEST_TYPE = 'extended_acceptance_test';
+    /* end tags */
+
+    /**
+     * Page Index.
+     *
+     * @var synonymGroupIndex
+     */
+    protected $synonymGroupIndex;
+
+    /**
+     * Page synonymGroupNew.
+     *
+     * @var SynonymGroupNew
+     */
+    protected $synonymGroupNew;
+
+    /**
+     * Injection data.
+     *
+     * @param SynonymGroupIndex $synonymGroupIndex
+     * @param SynonymGroupNew $synonymGroupNew
+     * @return void
+     */
+    public function __inject(
+        SynonymGroupIndex $synonymGroupIndex,
+        SynonymGroupNew $synonymGroupNew
+    ) {
+        $this->synonymGroupIndex = $synonymGroupIndex;
+        $this->synonymGroupNew = $synonymGroupNew;
+    }
+
+    /**
+     * Update Synonym Group.
+     *
+     * @param SynonymGroup $initialSynonymGroup
+     * @return void
+     */
+    public function test(SynonymGroup $initialSynonymGroup)
+    {
+        //precondition
+        $initialSynonymGroup->persist();
+
+        $initialData = ($initialSynonymGroup->getData());
+        $synonyms = $initialData['synonyms'];
+
+        // Steps
+        $this->synonymGroupIndex->open();
+        $this->synonymGroupIndex->getSynonymGroupGrid()->searchAndOpen(['synonyms' => $synonyms]);
+        $this->synonymGroupNew->getFormPageActions()->delete();
+        $this->synonymGroupNew->getModalBlock()->acceptAlert();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/DeleteSynonymGroupEntityTest.xml b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/DeleteSynonymGroupEntityTest.xml
new file mode 100755
index 0000000000000000000000000000000000000000..e3c5140605307a8508675e0ef6f86a90796e577c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/DeleteSynonymGroupEntityTest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\Search\Test\TestCase\DeleteSynonymGroupEntityTest" summary="Delete Synonym Groups" ticketId="MAGETWO-47683">
+        <variation name="DeleteSynonymGroupEntityTestVariation1">
+            <data name="initialSynonymGroup/dataset" xsi:type="string">prepareMerge</data>
+            <data name="description" xsi:type="string">Delete Synonym Groups Successfully</data>
+            <data name="tag" xsi:type="string">test_type:extended_acceptance_test</data>
+            <constraint name="Magento\Search\Test\Constraint\AssertSynonymGroupDeleteMessage" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/MergeSynonymGroupEntityTest.php b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/MergeSynonymGroupEntityTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2927856876a059bbbcb7e2c580c997ff67df6ed7
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/MergeSynonymGroupEntityTest.php
@@ -0,0 +1,105 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Search\Test\TestCase;
+
+use Magento\Search\Test\Page\Adminhtml\SynonymGroupIndex;
+use Magento\Search\Test\Page\Adminhtml\SynonymGroupNew;
+use Magento\Mtf\TestCase\Injectable;
+use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Search\Test\Fixture\SynonymGroup;
+
+/**
+ * Preconditions:
+ * 1. Create Synonym Group view.
+ *
+ * Steps:
+ * 1. Open Backend.
+ * 2. Go to Marketing > Search Synonyms.
+ * 3. Click "New Synonym Group" button.
+ * 4. Fill data according to dataset.
+ * 5. Perform all assertions.
+ *
+ * @group Search_(MX)
+ * @ZephyrId MAGETWO-47684
+ */
+class MergeSynonymGroupEntityTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    const DOMAIN = 'MX';
+    const TEST_TYPE = 'extended_acceptance_test';
+    /* end tags */
+
+    /**
+     * Page Index.
+     *
+     * @var synonymGroupIndex
+     */
+    protected $synonymGroupIndex;
+
+    /**
+     * Page synonymGroupNew.
+     *
+     * @var SynonymGroupNew
+     */
+    protected $synonymGroupNew;
+
+    /**
+     * Fixture Factory.
+     *
+     * @var FixtureFactory
+     */
+    protected $factory;
+
+    /**
+     * Injection data.
+     *
+     * @param SynonymGroupIndex $synonymGroupIndex
+     * @param SynonymGroupNew $synonymGroupNew
+     * @param FixtureFactory $factory
+     * @return void
+     */
+    public function __inject(
+        SynonymGroupIndex $synonymGroupIndex,
+        SynonymGroupNew $synonymGroupNew,
+        FixtureFactory $factory
+    ) {
+        $this->synonymGroupIndex = $synonymGroupIndex;
+        $this->synonymGroupNew = $synonymGroupNew;
+        $this->factory = $factory;
+    }
+
+    /**
+     * Merge Synonym Group.
+     *
+     * @param SynonymGroup $initialSynonymGroup
+     * @param SynonymGroup $synonymGroup
+     * @return void
+     */
+    public function test(SynonymGroup $initialSynonymGroup, SynonymGroup $synonymGroup)
+    {
+        //precondition
+        $initialSynonymGroup->persist();
+
+        $initialData = ($initialSynonymGroup->getData());
+        $synonyms = $initialData['synonyms'];
+        $synonyms = explode(',', $synonyms);
+        $data = $synonymGroup->getData();
+        $data['synonyms'] = $synonyms[0] . ',' . $data['synonyms'];
+        $data['scope_id'] = [
+            'dataset' => 'default_store_view'
+        ];
+
+        $synonymGroup = $this->factory->createByCode('synonymGroup', ['data' => $data]);
+
+        // Steps
+        $this->synonymGroupIndex->open();
+        $this->synonymGroupIndex->getGridPageActions()->addNew();
+        $this->synonymGroupNew->getSynonymGroupForm()->fill($synonymGroup);
+        $this->synonymGroupNew->getFormPageActions()->save();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/MergeSynonymGroupEntityTest.xml b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/MergeSynonymGroupEntityTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9c9d886d494653f56779876fb9c72b26c917e59c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/MergeSynonymGroupEntityTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\Search\Test\TestCase\MergeSynonymGroupEntityTest" summary="Merge Synonym Groups" ticketId="MAGETWO-47684">
+        <variation name="MergeSynonymGroupEntityTestVariation1">
+            <data name="initialSynonymGroup/dataset" xsi:type="string">prepareMerge</data>
+            <data name="description" xsi:type="string">Merge Synonym Groups Not Successfully</data>
+            <data name="tag" xsi:type="string">test_type:extended_acceptance_test</data>
+            <data name="synonymGroup/data/synonyms" xsi:type="string">synonym_test_%isolation%</data>
+            <data name="synonymGroup/data/scope_id/dataset" xsi:type="string">default_store_view</data>
+            <data name="synonymGroup/data/mergeOnConflict" xsi:type="string">No</data>
+            <constraint name="Magento\Search\Test\Constraint\AssertSynonymMergeErrorMessage" />
+        </variation>
+        <variation name="MergeSynonymGroupEntityTestVariation2">
+            <data name="initialSynonymGroup/dataset" xsi:type="string">prepareMerge</data>
+            <data name="description" xsi:type="string">Merge Synonym Groups Successfully</data>
+            <data name="tag" xsi:type="string">test_type:extended_acceptance_test</data>
+            <data name="synonymGroup/data/synonyms" xsi:type="string">shoes_%isolation%,foot wear_%isolation%,mens shoes_%isolation%,women shoes_%isolation%</data>
+            <data name="synonymGroup/data/scope_id/dataset" xsi:type="string">default_store_view</data>
+            <data name="synonymGroup/data/mergeOnConflict" xsi:type="string">Yes</data>
+            <constraint name="Magento\Search\Test\Constraint\AssertSynonymGroupSuccessSaveMessage" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/UpdateSynonymGroupEntityTest.php b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/UpdateSynonymGroupEntityTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..de0a52e459582130e9315ea0738ddea9fff4f397
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/UpdateSynonymGroupEntityTest.php
@@ -0,0 +1,97 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Search\Test\TestCase;
+
+use Magento\Search\Test\Page\Adminhtml\SynonymGroupIndex;
+use Magento\Search\Test\Page\Adminhtml\SynonymGroupNew;
+use Magento\Mtf\TestCase\Injectable;
+use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Search\Test\Fixture\SynonymGroup;
+
+/**
+ * Preconditions:
+ * 1. Create Synonym Group view.
+ *
+ * Steps:
+ * 1. Open Backend.
+ * 2. Go to Marketing > Search Synonyms.
+ * 3. Open created Synonym Group.
+ * 4. Fill data according to dataset.
+ * 5. Perform all assertions.
+ *
+ * @group Search_(MX)
+ * @ZephyrId MAGETWO-49412
+ */
+class UpdateSynonymGroupEntityTest extends Injectable
+{
+    /* tags */
+    const MVP = 'yes';
+    const DOMAIN = 'MX';
+    const TEST_TYPE = 'extended_acceptance_test';
+    /* end tags */
+
+    /**
+     * Page Index.
+     *
+     * @var synonymGroupIndex
+     */
+    protected $synonymGroupIndex;
+
+    /**
+     * Page synonymGroupNew.
+     *
+     * @var SynonymGroupNew
+     */
+    protected $synonymGroupNew;
+
+    /**
+     * Fixture Factory.
+     *
+     * @var FixtureFactory
+     */
+    protected $factory;
+
+    /**
+     * Injection data.
+     *
+     * @param SynonymGroupIndex $synonymGroupIndex
+     * @param SynonymGroupNew $synonymGroupNew
+     * @param FixtureFactory $factory
+     * @return void
+     */
+    public function __inject(
+        SynonymGroupIndex $synonymGroupIndex,
+        SynonymGroupNew $synonymGroupNew,
+        FixtureFactory $factory
+    ) {
+        $this->synonymGroupIndex = $synonymGroupIndex;
+        $this->synonymGroupNew = $synonymGroupNew;
+        $this->factory = $factory;
+    }
+
+    /**
+     * Update Synonym Group.
+     *
+     * @param SynonymGroup $initialSynonymGroup
+     * @param SynonymGroup $synonymGroup
+     * @return void
+     */
+    public function test(SynonymGroup $initialSynonymGroup, SynonymGroup $synonymGroup)
+    {
+        //precondition
+        $initialSynonymGroup->persist();
+
+        $initialData = ($initialSynonymGroup->getData());
+        $synonyms = $initialData['synonyms'];
+
+        // Steps
+        $this->synonymGroupIndex->open();
+        $this->synonymGroupIndex->getSynonymGroupGrid()->searchAndOpen(['synonyms' => $synonyms]);
+        $this->synonymGroupNew->getSynonymGroupForm()->fill($synonymGroup);
+        $this->synonymGroupNew->getFormPageActions()->save();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/UpdateSynonymGroupEntityTest.xml b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/UpdateSynonymGroupEntityTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d59e0e919fbc6095dc990f38e358b4e1a06d7b76
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/TestCase/UpdateSynonymGroupEntityTest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\Search\Test\TestCase\UpdateSynonymGroupEntityTest" summary="Update Synonym Groups" ticketId="MAGETWO-49412">
+        <variation name="UpdateSynonymGroupEntityTestVariation1">
+            <data name="initialSynonymGroup/dataset" xsi:type="string">prepareMerge</data>
+            <data name="description" xsi:type="string">Update Synonym Groups Successfully</data>
+            <data name="tag" xsi:type="string">test_type:extended_acceptance_test</data>
+            <data name="synonymGroup/data/synonyms" xsi:type="string">new_synonym_%isolation%</data>
+            <data name="synonymGroup/data/scope_id/dataset" xsi:type="string">all_store_views</data>
+            <constraint name="Magento\Search\Test\Constraint\AssertSynonymGroupSuccessSaveMessage" />
+            <constraint name="Magento\Search\Test\Constraint\AssertSynonymGroupInGrid" />
+        </variation>
+    </testCase>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/etc/curl/di.xml b/dev/tests/functional/tests/app/Magento/Search/Test/etc/curl/di.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5dad85c0b7ec68e2abdf2120c91f525f42675563
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/etc/curl/di.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
+    <preference for="\Magento\Search\Test\Handler\SynonymGroup\SynonymGroupInterface" type="\Magento\Search\Test\Handler\SynonymGroup\Curl" />
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Search/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Search/Test/etc/di.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9d651d917789f38e8c34a6eb903b18613f888657
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Search/Test/etc/di.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
+    <type name="Magento\Search\Test\Constraint\AssertSynonymGroupSuccessSaveMessage">
+        <arguments>
+            <argument name="severity" xsi:type="string">high</argument>
+        </arguments>
+    </type>
+    <type name="Magento\Search\Test\Constraint\AssertSynonymGroupDeleteMessage">
+        <arguments>
+            <argument name="severity" xsi:type="string">high</argument>
+        </arguments>
+    </type>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Store.xml b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Store.xml
index f14e959ce90cb0b427f74598ca9db7459259c828..672fd79994df8bb3e983f116d73bab3f42a69f03 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Store.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Store.xml
@@ -44,5 +44,13 @@
             <field name="code" xsi:type="string">de%isolation%</field>
             <field name="is_active" xsi:type="string">Enabled</field>
         </dataset>
+        <dataset name="custom_store">
+            <field name="group_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">custom_new_group</item>
+            </field>
+            <field name="name" xsi:type="string">Store_%isolation%</field>
+            <field name="code" xsi:type="string">store_%isolation%</field>
+            <field name="is_active" xsi:type="string">Enabled</field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/StoreGroup.xml b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/StoreGroup.xml
index b04cb4b8af12cd7d61dcd23f704dde49b78037ed..c7c2083d9bc0aefbf38fd6062178c7f971add39c 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/StoreGroup.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/StoreGroup.xml
@@ -27,5 +27,15 @@
                 <item name="dataset" xsi:type="string">default_category</item>
             </field>
         </dataset>
+
+        <dataset name="custom_new_group">
+            <field name="website_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">custom_website</item>
+            </field>
+            <field name="name" xsi:type="string">store_name_%isolation%</field>
+            <field name="root_category_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default_category</item>
+            </field>
+        </dataset>
     </repository>
 </config>
diff --git a/dev/tests/integration/framework/Magento/TestFramework/Application.php b/dev/tests/integration/framework/Magento/TestFramework/Application.php
index 93c62f8c0c141dca8916872fe725129f6f83407b..2c38a3e724eb357d8c6ea1c09fe3ac70f753e340 100644
--- a/dev/tests/integration/framework/Magento/TestFramework/Application.php
+++ b/dev/tests/integration/framework/Magento/TestFramework/Application.php
@@ -427,7 +427,7 @@ class Application
          * @see \Magento\Setup\Mvc\Bootstrap\InitParamListener::BOOTSTRAP_PARAM
          */
         $this->_shell->execute(
-            'php -f %s setup:uninstall -n --magento-init-params=%s',
+            PHP_BINARY . ' -f %s setup:uninstall -vvv -n --magento-init-params=%s',
             [BP . '/bin/magento', $this->getInitParamsQuery()]
         );
     }
@@ -460,15 +460,18 @@ class Application
 
         // run install script
         $this->_shell->execute(
-            'php -f %s setup:install ' . implode(' ', array_keys($installParams)),
+            PHP_BINARY . ' -f %s setup:install -vvv ' . implode(' ', array_keys($installParams)),
             array_merge([BP . '/bin/magento'], array_values($installParams))
         );
 
         // enable only specified list of caches
         $initParamsQuery = $this->getInitParamsQuery();
-        $this->_shell->execute('php -f %s cache:disable --bootstrap=%s', [BP . '/bin/magento', $initParamsQuery]);
         $this->_shell->execute(
-            'php -f %s cache:enable %s %s %s %s --bootstrap=%s',
+            PHP_BINARY . ' -f %s cache:disable -vvv --bootstrap=%s',
+            [BP . '/bin/magento', $initParamsQuery]
+        );
+        $this->_shell->execute(
+            PHP_BINARY . ' -f %s cache:enable -vvv %s %s %s %s --bootstrap=%s',
             [
                 BP . '/bin/magento',
                 \Magento\Framework\App\Cache\Type\Config::TYPE_IDENTIFIER,
diff --git a/dev/tests/integration/testsuite/Magento/Theme/Observer/ThemeRegistrationObserverTest.php b/dev/tests/integration/testsuite/Magento/Theme/Observer/ThemeRegistrationObserverTest.php
deleted file mode 100644
index d4f7b8f2a8a2674ce92068153648d8fe9070504e..0000000000000000000000000000000000000000
--- a/dev/tests/integration/testsuite/Magento/Theme/Observer/ThemeRegistrationObserverTest.php
+++ /dev/null
@@ -1,75 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-/**
- * Test theme observer
- */
-namespace Magento\Theme\Observer;
-
-class ThemeRegistrationObserverTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * @var \Magento\Framework\Event\Observer
-     */
-    protected $_eventObserver;
-
-    /**
-     * @var \Magento\TestFramework\ObjectManager
-     */
-    protected $_objectManager;
-
-    protected function setUp()
-    {
-        $this->_objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-        $this->_eventObserver = $this->_createEventObserverForThemeRegistration();
-    }
-
-    /**
-     * Theme registration test
-     *
-     * @magentoDbIsolation enabled
-     * @magentoAppIsolation enabled
-     */
-    public function testThemeRegistration()
-    {
-        $themeRegistration = $this->getMock(
-            'Magento\Theme\Model\Theme\Registration',
-            ['register'],
-            [
-                $this->_objectManager->create('Magento\Theme\Model\ResourceModel\Theme\Data\CollectionFactory'),
-                $this->_objectManager->create('Magento\Theme\Model\Theme\Data\Collection'),
-                $this->_objectManager->create('Magento\Framework\Filesystem')
-            ]
-        );
-        $themeRegistration->expects($this->once())->method('register');
-        $this->_objectManager->addSharedInstance($themeRegistration, 'Magento\Theme\Model\Theme\Registration');
-
-        /** @var $observer \Magento\Theme\Observer\ThemeRegistrationObserver */
-        $observer = $this->_objectManager->create('Magento\Theme\Observer\ThemeRegistrationObserver');
-        $observer->execute($this->_eventObserver);
-    }
-
-    /**
-     * Create event observer for theme registration
-     *
-     * @return \Magento\Framework\Event\Observer
-     */
-    protected function _createEventObserverForThemeRegistration()
-    {
-        $response = $this->_objectManager->create(
-            'Magento\Framework\DataObject',
-            ['data' => ['additional_options' => []]]
-        );
-        $event = $this->_objectManager->create(
-            'Magento\Framework\Event',
-            ['data' => ['response_object' => $response]]
-        );
-        return $this->_objectManager->create(
-            'Magento\Framework\Event\Observer',
-            ['data' => ['event' => $event]]
-        );
-    }
-}
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php
index 085270afadeabd18bcb57fcbb4e752b9cfbb4ee6..cb7c70c581392fc2ceccb2a95f4f77bcba457107 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php
@@ -5,26 +5,15 @@
  */
 namespace Magento\Test\Integrity;
 
+use Magento\Framework\App\Bootstrap;
 use Magento\Framework\Component\ComponentRegistrar;
 use Magento\Framework\Composer\MagentoComponent;
-use Magento\Framework\App\Utility\Files;
-use Magento\Framework\Shell;
-use Magento\Framework\Exception\LocalizedException;
 
 /**
  * A test that enforces validity of composer.json files and any other conventions in Magento components
  */
 class ComposerTest extends \PHPUnit_Framework_TestCase
 {
-    /**
-     * @var \Magento\Framework\Shell
-     */
-    private static $shell;
-
-    /**
-     * @var bool
-     */
-    private static $isComposerAvailable;
 
     /**
      * @var string
@@ -42,20 +31,16 @@ class ComposerTest extends \PHPUnit_Framework_TestCase
     private static $dependencies;
 
     /**
-     * @var string
+     * @var \Magento\Framework\ObjectManagerInterface
      */
-    private static $composerPath = 'composer';
+    private static $objectManager;
 
     public static function setUpBeforeClass()
     {
-        if (defined('TESTS_COMPOSER_PATH')) {
-            self::$composerPath = TESTS_COMPOSER_PATH;
-        }
-        self::$shell = self::createShell();
-        self::$isComposerAvailable = self::isComposerAvailable();
         self::$root = BP;
         self::$rootJson = json_decode(file_get_contents(self::$root . '/composer.json'), true);
         self::$dependencies = [];
+        self::$objectManager = Bootstrap::create(BP, $_SERVER)->getObjectManager();
     }
 
     public function testValidComposerJson()
@@ -111,9 +96,10 @@ class ComposerTest extends \PHPUnit_Framework_TestCase
      */
     private function validateComposerJsonFile($path)
     {
-        if (self::$isComposerAvailable) {
-            self::$shell->execute(self::$composerPath . ' validate --working-dir=%s', [$path]);
-        }
+        /** @var \Magento\Framework\Composer\MagentoComposerApplicationFactory $appFactory */
+        $appFactory = self::$objectManager->get('Magento\Framework\Composer\MagentoComposerApplicationFactory');
+        $app = $appFactory->create();
+        $app->runComposerCommand(['command' => 'validate'], $path);
     }
 
     /**
@@ -333,31 +319,6 @@ class ComposerTest extends \PHPUnit_Framework_TestCase
         return strtolower("{$vendor}/{$package}");
     }
 
-    /**
-     * Create shell wrapper
-     *
-     * @return \Magento\Framework\Shell
-     */
-    private static function createShell()
-    {
-        return new Shell(new Shell\CommandRenderer, null);
-    }
-
-    /**
-     * Check if composer command is available in the environment
-     *
-     * @return bool
-     */
-    private static function isComposerAvailable()
-    {
-        try {
-            self::$shell->execute(self::$composerPath . ' --version');
-        } catch (LocalizedException $e) {
-            return false;
-        }
-        return true;
-    }
-
     public function testComponentPathsInRoot()
     {
         if (!isset(self::$rootJson['extra']) || !isset(self::$rootJson['extra']['component_paths'])) {
diff --git a/lib/internal/Magento/Framework/Backup/Snapshot.php b/lib/internal/Magento/Framework/Backup/Snapshot.php
index f01a1a874f8ecec8bad3cc64624ef9c820046e14..091c3830f5d06ed811a143f35b648318416e1d5e 100644
--- a/lib/internal/Magento/Framework/Backup/Snapshot.php
+++ b/lib/internal/Magento/Framework/Backup/Snapshot.php
@@ -113,7 +113,7 @@ class Snapshot extends Filesystem
     protected function _createDbBackupInstance()
     {
         return $this->_backupFactory->create(Factory::TYPE_DB)
-            ->setBackupExtension('gz')
+            ->setBackupExtension('sql')
             ->setTime($this->getTime())
             ->setBackupsDir($this->_filesystem->getDirectoryWrite(DirectoryList::VAR_DIR)->getAbsolutePath())
             ->setResourceModel($this->getResourceModel());
diff --git a/lib/internal/Magento/Framework/Backup/Test/Unit/SnapshotTest.php b/lib/internal/Magento/Framework/Backup/Test/Unit/SnapshotTest.php
index ce941c3ee90b601ca841bb335dd3c244f46b0573..e725fa0d1c17491eb37d67bff2d10a89550762a5 100644
--- a/lib/internal/Magento/Framework/Backup/Test/Unit/SnapshotTest.php
+++ b/lib/internal/Magento/Framework/Backup/Test/Unit/SnapshotTest.php
@@ -17,7 +17,7 @@ class SnapshotTest extends \PHPUnit_Framework_TestCase
             [$filesystem, $backupFactory]
         );
 
-        $file = 'var/backup/2.gz';
+        $file = 'var/backup/2.sql';
         $manager->expects($this->once())->method('getBackupFilename')->will($this->returnValue($file));
 
         $model = new \Magento\Framework\Backup\Snapshot($filesystem, $backupFactory);
diff --git a/lib/internal/Magento/Framework/Currency.php b/lib/internal/Magento/Framework/Currency.php
index 94fc8d579d373ade20b5dd90b634a390038426e5..26c1acaf295f754e68e864f0c4d3fc04bc0595be 100644
--- a/lib/internal/Magento/Framework/Currency.php
+++ b/lib/internal/Magento/Framework/Currency.php
@@ -5,6 +5,25 @@
  */
 namespace Magento\Framework;
 
-class Currency extends \Zend_Currency implements \Magento\Framework\CurrencyInterface
+use Magento\Framework\App\CacheInterface;
+
+class Currency extends \Zend_Currency implements CurrencyInterface
 {
+    /**
+     * Creates a currency instance.
+     *
+     * @param CacheInterface $appCache
+     * @param string|array $options Options array or currency short name when string is given
+     * @param string $locale Locale name
+     */
+    public function __construct(
+        CacheInterface $appCache,
+        $options = null,
+        $locale = null
+    ) {
+        // set Zend cache to low level frontend app cache
+        $lowLevelFrontendCache = $appCache->getFrontend()->getLowLevelFrontend();
+        \Zend_Currency::setCache($lowLevelFrontendCache);
+        parent::__construct($options, $locale);
+    }
 }
diff --git a/lib/internal/Magento/Framework/Setup/BackupRollback.php b/lib/internal/Magento/Framework/Setup/BackupRollback.php
index 92b7a127112778a72cc74149848bf83fc59e17d4..fff94707ba7bbb695f02dcf317e3378e3984bc7c 100644
--- a/lib/internal/Magento/Framework/Setup/BackupRollback.php
+++ b/lib/internal/Magento/Framework/Setup/BackupRollback.php
@@ -204,14 +204,11 @@ class BackupRollback
             $this->file->createDirectory($this->backupsDir, DriverInterface::WRITEABLE_DIRECTORY_MODE);
         }
         $dbBackup->setBackupsDir($this->backupsDir);
-        $dbBackup->setBackupExtension('gz');
+        $dbBackup->setBackupExtension('sql');
         $dbBackup->setTime($time);
         $this->log->log('DB backup is starting...');
         $dbBackup->create();
-        $this->log->log(
-            'DB backup filename: ' . $dbBackup->getBackupFilename()
-            . ' (The archive can be uncompressed with 7-Zip on Windows systems)'
-        );
+        $this->log->log('DB backup filename: ' . $dbBackup->getBackupFilename());
         $this->log->log('DB backup path: ' . $dbBackup->getBackupPath());
         $this->log->logSuccess('DB backup completed successfully.');
         return $dbBackup->getBackupPath();
@@ -226,7 +223,7 @@ class BackupRollback
      */
     public function dbRollback($rollbackFile)
     {
-        if (preg_match('/[0-9]_(db)(.*?).(gz)$/', $rollbackFile) !== 1) {
+        if (preg_match('/[0-9]_(db)(.*?).(sql)$/', $rollbackFile) !== 1) {
             throw new LocalizedException(new Phrase('Invalid rollback file.'));
         }
         if (!$this->file->isExists($this->backupsDir . '/' . $rollbackFile)) {
@@ -236,7 +233,7 @@ class BackupRollback
         $dbRollback = $this->objectManager->create('Magento\Framework\Backup\Db');
         $dbRollback->setRootDir($this->directoryList->getRoot());
         $dbRollback->setBackupsDir($this->backupsDir);
-        $dbRollback->setBackupExtension('gz');
+        $dbRollback->setBackupExtension('sql');
         $time = explode('_', $rollbackFile);
         if (count($time) === 3) {
             $thirdPart = explode('.', $time[2]);
diff --git a/lib/internal/Magento/Framework/Setup/Test/Unit/BackupRollbackTest.php b/lib/internal/Magento/Framework/Setup/Test/Unit/BackupRollbackTest.php
index 3a5a6b838b0f0fb1607b017e1a0e80a3e5e45da8..cb9682b52d1d609234e2800f8303395a606ce5a0 100644
--- a/lib/internal/Magento/Framework/Setup/Test/Unit/BackupRollbackTest.php
+++ b/lib/internal/Magento/Framework/Setup/Test/Unit/BackupRollbackTest.php
@@ -188,9 +188,9 @@ class BackupRollbackTest extends \PHPUnit_Framework_TestCase
         $this->database->expects($this->once())->method('rollback');
         $this->file->expects($this->once())
             ->method('isExists')
-            ->with($this->path . '/backups/12345_db.gz')
+            ->with($this->path . '/backups/12345_db.sql')
             ->willReturn(true);
-        $this->model->dbRollback('12345_db.gz');
+        $this->model->dbRollback('12345_db.sql');
     }
 
     private function setupCodeBackupRollback()
@@ -226,7 +226,7 @@ class BackupRollbackTest extends \PHPUnit_Framework_TestCase
             ->willReturn('RollbackFile_A.gz');
         $this->database->expects($this->atLeastOnce())
             ->method('getBackupPath')
-            ->willReturn('pathToFile/12345_db.tgz');
+            ->willReturn('pathToFile/12345_db.sql');
         $this->log->expects($this->once())
             ->method('logSuccess');
     }
diff --git a/lib/internal/Magento/Framework/Test/Unit/CurrencyTest.php b/lib/internal/Magento/Framework/Test/Unit/CurrencyTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..28b71773244dd30d35ffc78c9fd84a0c9ad2d676
--- /dev/null
+++ b/lib/internal/Magento/Framework/Test/Unit/CurrencyTest.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Test\Unit;
+
+use Magento\Framework\Currency;
+
+/**
+ * Test for Magento\Framework\Currency
+ */
+class CurrencyTest extends \PHPUnit_Framework_TestCase
+{
+    public function testConstruct()
+    {
+        $frontendCache = $this->getMock('Magento\Framework\Cache\FrontendInterface', [], [], '', false, false);
+        $lowLevelFrontend = $this->getMock('Zend_Cache_Core', [], [], '', false, false);
+        /** @var \Magento\Framework\App\CacheInterface|\PHPUnit_Framework_MockObject_MockObject $appCache */
+        $appCache = $this->getMock('Magento\Framework\App\CacheInterface', [], [], '', false, false);
+        $frontendCache->expects($this->once())->method('getLowLevelFrontend')->willReturn($lowLevelFrontend);
+        $appCache->expects($this->once())
+            ->method('getFrontend')
+            ->willReturn($frontendCache);
+
+        // Create new currency object
+        $currency = new Currency($appCache, null, 'en_US');
+        $this->assertEquals($lowLevelFrontend, $currency->getCache());
+        $this->assertEquals('USD', $currency->getShortName());
+    }
+}
diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php
index c4a9e916c87dfbbbd72407c5b49fb206337d922d..5f3678b7bf628f59ce317f96c7fa9cb9615b187d 100644
--- a/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php
+++ b/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/FulltextFilter.php
@@ -37,11 +37,11 @@ class FulltextFilter implements FilterApplierInterface
      * Add table alias to columns
      *
      * @param array $columns
-     * @param DbCollection $collection
+     * @param AbstractDb $collection
      * @param string $indexTable
      * @return array
      */
-    protected function addTableAliasToColumns(array $columns, DbCollection $collection, $indexTable)
+    protected function addTableAliasToColumns(array $columns, AbstractDb $collection, $indexTable)
     {
         $alias = '';
         foreach ($collection->getSelect()->getPart('from') as $tableAlias => $data) {
@@ -76,7 +76,7 @@ class FulltextFilter implements FilterApplierInterface
         }
 
         /** @var AbstractDb $collection */
-        $columns = $this->getFulltextIndexColumns($collection, $collection->getResource()->getMainTable());
+        $columns = $this->getFulltextIndexColumns($collection, $collection->getMainTable());
         if (!$columns) {
             return;
         }
diff --git a/phpserver/README.md b/phpserver/README.md
index 2c783f05603f952e7651a05bb27f982462119ebe..1dcccffb549be918d7cdcac9d917a2bc3cd2ebaa 100644
--- a/phpserver/README.md
+++ b/phpserver/README.md
@@ -1,35 +1,60 @@
 PHP Built-in webserver
 ======================
 
-php has a Built-in webserver since version 5.4
-https://secure.php.net/manual/en/features.commandline.webserver.php
+PHP has had a <a href="https://secure.php.net/manual/en/features.commandline.webserver.php" target="_blank">built-in web sever</a> since version 5.4.
 
-As many applications and frameworks rely on rewrites on webserver side,
-the same as Magento does, it offers an argument for a router script.
-Either the script returns false which means, it should try to deliver the file
-as usual via file system lookup, or it executes the specific php scripts via include.
+PHP's web server provides a router script for use with server rewrites. Magento, like many other applications and frameworks, requires server rewrites. The router script either:
+- The web server executes the requested PHP script using a server-side include
+- Returns `false`, which means the web server returns the file using file system lookup
 
 Example:
 requests to `/static/frontend/Magento/blank/en_US/mage/calendar.css` should deliver the file if it exists, or execute `/static.php` if not.
 
 Without a router script, that is not possible via the php built-in server.
 
-### How to use it
+### How to install Magento
 
-example usage: ```php -S 127.0.0.41:8082 -t ./pub/ ./phpserver/router.php```
+Magento's web-based Setup Wizard runs from the `setup` subdirectory, which PHP's built-in web server cannot route. Therefore, you must install Magento using the <a href="http://devdocs.magento.com/guides/v2.0/install-gde/install/cli/install-cli.html" target="_blank">command line</a>. An example follows:
+
+```
+php bin/magento setup:install --base-url=http://127.0.0.1:8082 
+--db-host=localhost --db-name=magento --db-user=magento --db-password=magento
+--admin-firstname=Magento --admin-lastname=User --admin-email=user@example.com
+--admin-user=admin --admin-password=admin123 --language=en_US
+--currency=USD --timezone=America/Chicago --use-rewrites=0
+```
+
+It's important to note that the router is not able to work with rewrite urls, that's why the flag `use-rewrites` is set to `0`.
+
+Notes:
+- You must use `--use-rewrites=0` because the web server cannot rewrite URLs
+- By default, Magento creates a random Admin URI for you. Make sure to write this value down because it's how you access the Magento Admin later. For example : ```http://127.0.0.1:8082/index.php/admin_1vpn01```.
+
+For more informations about the installation process using the CLI, you can consult the dedicated documentation that can found in [the developer documentation](https://github.com/magento/devdocs/blob/develop/guides/v2.0/install-gde/install/cli/install-cli-install.md).
+
+### How to run Magento
+
+Example usage: ```php -S 127.0.0.1:8082 -t ./pub/ ./phpserver/router.php```
 
 ### What exactly the script does
 
-first we have an low level `$debug` closure, for the case you need to debug execution.
+The `$debug` option provides low-level logging for debugging purposes.
 
-If the request path starts with index.php, get.php, static.php, we return to normal request flow.
-If we notice a favicon.ico request, the same.
+Forwarding rules:
+- Any request for `favicon.ico` or for any path that starts with `index.php`, `get.php`, `static.php` are processed normally.
+- Requests for the path `pub/errors/default` are rewritten as `errors/default`. This is provided for compatibility with older versions.
+- Files under request paths `media`, `opt`, or `static` are tested; if the file exists, the file is served. If the file does not exist, `static` files are forwarded to `static.php` and `media` files are forwarded to `get.php` ((How about `opt`?))
+- If no rules are matched, return a 404 (Not Found).
 
 Then rewrite paths for `pub/errors/default/` by removing the `pub/` part. (was at least needed for older versions)
 
-Request starting with `media/`, `opt/`, `static/` test if the file exists.
-If Yes, then handle it, if not "forward" `static` to `static.php` and `media` to `get.php`
+Request starting with `media/`, `opt/`, `static/` test if the file exists. If Yes, then handle it, if not "forward" `static` to `static.php` and `media` to `get.php`
+
+If none of the rules matched, return 404. You may instead include the index.php, if 404 should be handled by Magento or you want urls without `index.php/`.
+
+### How to access to the admin dashboard
+
+When the installation is finished, you can access Magento as follows:
+- Storefront: `<your Magento base URL>`
+- Magento Admin: `<your Magento base URL>/<admin URI>`
 
-If none of the rules matched, return 404.
-You may instead include the index.php, if 404 should be handled by Magento or you want
-urls without `index.php/`.
diff --git a/setup/src/Magento/Setup/Model/FilePermissions.php b/setup/src/Magento/Setup/Model/FilePermissions.php
index f187859907872c2e90e693ec276a8f8618da7db6..77b746e0f156ccf9ca5fc1313778cedc195e8695 100644
--- a/setup/src/Magento/Setup/Model/FilePermissions.php
+++ b/setup/src/Magento/Setup/Model/FilePermissions.php
@@ -151,7 +151,7 @@ class FilePermissions
 
         try {
             foreach ($directoryIterator as $subDirectory) {
-                if (!$subDirectory->isWritable()) {
+                if (!$subDirectory->isWritable() && !$subDirectory->isLink()) {
                     $this->nonWritablePathsInDirectories[$directory][] = $subDirectory;
                     $foundNonWritable = true;
                 }
diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php
index 63606fdc811fa3930cee1c1b4ff60b96f70d301b..43a2c3a836294a9e644f3c6132de169805d0f869 100644
--- a/setup/src/Magento/Setup/Model/Installer.php
+++ b/setup/src/Magento/Setup/Model/Installer.php
@@ -95,7 +95,7 @@ class Installer
     /**
      * Deployment configuration reader
      *
-     * @var Writer
+     * @var Reader
      */
     private $deploymentConfigReader;
 
@@ -321,7 +321,7 @@ class Installer
         $script[] = ['Post installation file permissions check...', 'checkApplicationFilePermissions', []];
 
         $estimatedModules = $this->createModulesConfig($request, true);
-        $total = count($script) + 3 * count(array_filter($estimatedModules));
+        $total = count($script) + 4 * count(array_filter($estimatedModules));
         $this->progress = new Installer\Progress($total, 0);
 
         $this->log->log('Starting Magento installation:');
@@ -815,15 +815,19 @@ class Installer
 
         if ($type === 'schema') {
             $this->log->log('Schema post-updates:');
-            foreach ($moduleNames as $moduleName) {
-                $this->log->log("Module '{$moduleName}':");
-                $modulePostUpdater = $this->getSchemaDataHandler($moduleName, 'schema-recurring');
-                if ($modulePostUpdater) {
-                    $this->log->logInline("Running recurring.. ");
-                    $modulePostUpdater->install($setup, $moduleContextList[$moduleName]);
-                }
-                $this->logProgress();
+            $handlerType = 'schema-recurring';
+        } else if ($type === 'data') {
+            $this->log->log('Data post-updates:');
+            $handlerType = 'data-recurring';
+        }
+        foreach ($moduleNames as $moduleName) {
+            $this->log->log("Module '{$moduleName}':");
+            $modulePostUpdater = $this->getSchemaDataHandler($moduleName, $handlerType);
+            if ($modulePostUpdater) {
+                $this->log->logInline('Running ' + str_replace('-', ' ', $handlerType) + '...');
+                $modulePostUpdater->install($setup, $moduleContextList[$moduleName]);
             }
+            $this->logProgress();
         }
     }
 
@@ -1166,6 +1170,10 @@ class Installer
                 $className .= '\UpgradeData';
                 $interface = self::DATA_UPGRADE;
                 break;
+            case 'data-recurring':
+                $className .= '\RecurringData';
+                $interface = self::DATA_INSTALL;
+                break;
             default:
                 throw new \Magento\Setup\Exception("$className does not exist");
         }
diff --git a/setup/src/Magento/Setup/Module.php b/setup/src/Magento/Setup/Module.php
index be45abbb9dcd18c858712f2d781b02d98b7cf262..8ff27d9d9fafd74cb14a6a172a52c8c8b7d7da8a 100644
--- a/setup/src/Magento/Setup/Module.php
+++ b/setup/src/Magento/Setup/Module.php
@@ -6,6 +6,7 @@
 
 namespace Magento\Setup;
 
+use Magento\Framework\App\Response\HeaderProvider\XssProtection;
 use Magento\Setup\Mvc\View\Http\InjectTemplateListener;
 use Zend\EventManager\EventInterface;
 use Zend\ModuleManager\Feature\BootstrapListenerInterface;
@@ -50,6 +51,10 @@ class Module implements
                 $headers->addHeaderLine('Pragma', 'no-cache');
                 $headers->addHeaderLine('Expires', '1970-01-01');
                 $headers->addHeaderLine('X-Frame-Options: SAMEORIGIN');
+                $headers->addHeaderLine('X-Content-Type-Options: nosniff');
+                $xssHeaderValue = strpos($_SERVER['HTTP_USER_AGENT'], XssProtection::IE_8_USER_AGENT) === false
+                    ? XssProtection::HEADER_ENABLED : XssProtection::HEADER_DISABLED;
+                $headers->addHeaderLine('X-XSS-Protection: ' . $xssHeaderValue);
             }
         }
     }
diff --git a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php
index f415c5c19dbddc462a2efdeacb2c4bf6aa19a3ab..442002004a00359e7190f655407bafd26488cf5e 100644
--- a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php
@@ -292,12 +292,15 @@ class InstallerTest extends \PHPUnit_Framework_TestCase
         $this->logger->expects($this->at(26))->method('log')->with('Data install/update:');
         $this->logger->expects($this->at(27))->method('log')->with("Module 'Foo_One':");
         $this->logger->expects($this->at(29))->method('log')->with("Module 'Bar_Two':");
-        $this->logger->expects($this->at(32))->method('log')->with('Installing admin user...');
-        $this->logger->expects($this->at(34))->method('log')->with('Caches clearing:');
-        $this->logger->expects($this->at(37))->method('log')->with('Disabling Maintenance Mode:');
-        $this->logger->expects($this->at(39))->method('log')->with('Post installation file permissions check...');
-        $this->logger->expects($this->at(41))->method('logSuccess')->with('Magento installation complete.');
-        $this->logger->expects($this->at(43))->method('log')
+        $this->logger->expects($this->at(31))->method('log')->with('Data post-updates:');
+        $this->logger->expects($this->at(32))->method('log')->with("Module 'Foo_One':");
+        $this->logger->expects($this->at(34))->method('log')->with("Module 'Bar_Two':");
+        $this->logger->expects($this->at(37))->method('log')->with('Installing admin user...');
+        $this->logger->expects($this->at(39))->method('log')->with('Caches clearing:');
+        $this->logger->expects($this->at(42))->method('log')->with('Disabling Maintenance Mode:');
+        $this->logger->expects($this->at(44))->method('log')->with('Post installation file permissions check...');
+        $this->logger->expects($this->at(46))->method('logSuccess')->with('Magento installation complete.');
+        $this->logger->expects($this->at(48))->method('log')
             ->with('Sample Data is installed with errors. See log file for details');
         $this->object->install($request);
     }
diff --git a/setup/view/magento/setup/landing.phtml b/setup/view/magento/setup/landing.phtml
index f8fa886f73bc3fe3145c46973a55aabdc0147b2f..ffc77d1b8b73a778fd2ab8ade700b2d4749bd3cf 100644
--- a/setup/view/magento/setup/landing.phtml
+++ b/setup/view/magento/setup/landing.phtml
@@ -15,7 +15,7 @@
     <p class="text-welcome">
         Welcome to Magento Admin, your online store headquarters.
         <br>
-        Click 'Agree and Set Up Magento' or read <a href="http://devdocs.magento.com/guides/v1.0/install-gde/install/install-web.html" target="_blank">Getting Started</a> to learn more.
+        Click 'Agree and Set Up Magento' or read <a href="http://devdocs.magento.com/guides/v2.0/install-gde/install/web/install-web.html" target="_blank">Getting Started</a> to learn more.
     </p>
     <p class="text-terms">
         <a href="" ng-click="previousState()">Terms & Agreement</a>