diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4112fa4a01dedee365bbdcc83eb037be4fc7d4a5..174bd68b91babe9b25850685c8840fa2dc1294fb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,110 @@
+2.0.0.0-dev88
+=============
+* Fixed bugs:
+  * Fixed an issue when PayPal Express Checkout Payflow Edition and PayPal Payments Advanced were available for multiple checkout
+  * Fixed an issue when the Bill me later button did not redirect to https when secure url was enabled for frontend
+  * Fixed an issue when the Billing agreement option was available in multishipping checkout, even if there were no signed agreements
+  * Fixed an issue when DoExpressCheckout request instead of DoCapture did not allow to do refund, when using PayPal Express Checkout Payflow Edition
+  * Fixed an issue when eWay was not present on checkout if Base Currency was set to AUD
+  * Fixed an issue with fatal error occurring when placing order via SagePay with 3D Secure enabled
+  * Fixed an issue when the FedEx shipping method had no option to specify unit for weight attribute
+  * Fixed an issue with inability to create credit memo for PalPal Express Checkout/Payments Pro/Payments Pro Hosted Solution (NVP family), if partial refund was initiated on the PayPal side
+  * Fixed an issue when a guest user could not return product to store, if product was paid using PayPal
+  * Fixed an issue when PayPal Payments Pro Hosted Solution Fraud protection did not work properly
+  * Fixed an issue when JavaScript took values from default config for payment methods and used them on the website scope
+  * Fixed an issue with incorrect address in request to shipping carrier (DHL International) in case the address contained diacritic letters
+  * Fixed an issue when it was possible to hack currency in PayPal Website Payments Standard
+  * Fixed an issue when no rows were added to the PayPal Settlement report grid while fetching it from custom server
+  * Fixed an issue when order had the Suspected Fraud status after creating partial invoice on the PayPal side
+  * Fixed an issue when PayPal Payflow Pro did not properly implement CUSTREF and INVNUM
+  * Fixed an issue with PayPal errors handling during IPN postback
+  * Fixed an issue when the Paypal Express Checkout button was not available on product page for several product types
+  * Fixed an issue with PayPal Payflow Pro and Payflow Link broken unit tests
+  * Fixed an issue when PayPal Payments Pro Hosted Solution had the City parameter duplicated in the State parameter for UK
+  * Fixed an issue with remove multiple HTTP 100/101 headers
+  * Fixed an issue when SagePay did not transfer shopping cart information
+  * Fixed an issue when transaction records were absent on Transaction tab for Ogone
+  * Fixed an issue when partial cancel with SagePay Direct was unavailable
+  * Fixed an issue when order did not place using PayPal Payments Pro Hosted Solution
+  * Fixed an issue when order did not place using Authorize.net Direct Post from backend
+  * Fixed an issue when sort order for payment methods did not work
+  * Fixed an issue with multiple schema of language.xml
+  * Fixed an issue with infinite loop in language inheritance
+  * Fixed an issue with residual "scopes" logic in i18n implementation
+  * Fixed an issue when search did not work for the CMS Blocks grid
+  * Fixed an issue when WSDL for one scope was cached and displayed for all scopes
+  * Fixed an issue with unit tests coverage build failure
+  * Fixed an issue when custom options were lost after product import
+  * Fixed an issue when product did not show in backend grid if store contained several store view
+  * Fixed an issue when the Recurring Profile section was not updated after changing product template
+  * Fixed an issue with incorrect discount calculation
+  * Fixed an issue when customer could not register during Checkout if Guest Checkout was disabled
+  * Fixed an issue when shopping cart price rule was not applied after updating items and qty in the shopping cart
+  * Fixed an issue when updated and created dates were not shown for Billing Agreement in the Billing Agreement Grid in the backend
+  * Fixed an issue with broken design on the multiple addresses order review page
+  * Fixed an issue when sort by did not work in frontend for Yes/No attributes when Flat catalog was disabled
+  * Fixed an issue when a new blank CMS page was displayed after saving the CMS page entity
+  * Fixed an issue when product attributes were absent on the Product page after switching to another product template
+  * Fixed a 404 error after saving mass update product attributes form
+  * Fixed an issue when it was impossible to perform search by all tax classes on the Advanced Search page
+  * Fixed an issue when attribute order for configurable product was not preserved after saving product
+  * Fixed an issue with no results for the Product Best Sellers report
+  * Fixed a fatal error when opening tax configuration page in the backend
+  * Fixed an error occurring when opening the Tax Zones and Rates page in the backend
+  * Fixed a 404 error occurring while searching products on the New Review page
+  * Fixed an error when performing search in the Tax rate grid
+* Payments implementation:
+  * Ported correct behaviour for Fraud Management in PayPal Payflow Pro from M1 to M2
+  * Implemented ability to use negative line items for PayPal Payflowpro
+* Language packs:
+  * Implemented ability to use multiple packages for the same language from one vendor
+* GitHub requests:
+  * [#587] (https://github.com/magento/magento2/issues/587) --  The "install/Magento/basic/*_*/layout/*.xml" pattern cannot be processed in "/mnt/fs01/test/mdt/htdocs/app/design/" path Warning!Invalid argument supplied for foreach()
+* Unit tests coverage:
+  * Magento\Catalog\Model\Product
+* Service layer implementation:
+  * Created ConfigurableProduct service
+  * Created CompositeProduct service
+  * Refactored TaxCalculationService
+  * Refactored Google Shopping to use tax service
+  * Exposed TaxRate and TaxRule search functions as WebAPI TaxCalculationService
+  * Refactored QuoteDetails and QuoteDetailsItem to use tax class name
+  * Refactored gift wrapping to use tax/weee services
+  * Performed more tax refactoring for service layer
+  * Improved unit test coverage
+* Indexer-less implementation of URL Rewrites functionality in new UrlRedirect module:
+  * Implemented URL Rewrites generators for all entities: CMS page, product, category
+  * Implemented URL Rewrites matching in the frontend
+* Added the following functional tests:
+  * Activate Integration
+  * Add Compared Products
+  * Create Bundle Product
+  * Clear All Compare Products
+  * Create CMS Block
+  * Create CMS Page
+  * Create Custom Variable
+  * Create Integration
+  * Create Grouped Product
+  * Create Search Term
+  * Delete Assigned to Template Product Attribute
+  * Delete CMS Block
+  * Delete CMS Page Rewrite
+  * Delete Compare Products
+  * Delete Custom URL Rewrite
+  * Delete Integration
+  * Delete Product Template
+  * Duplicate Product
+  * Edit Search Term
+  * Update Bundle Product
+  * Update CMS Block
+  * Update CMS Page URL Rewrite
+  * Update Custom Variable
+  * Update Custom URL Rewrite
+  * Update Customer on Frontend
+  * Update Integration
+  * Update Product Template
+  * Update Virtual Product
+
 2.0.0.0-dev87
 =============
 * Service layer updates:
@@ -12,6 +119,7 @@
   * [#584] (https://github.com/magento/magento2/issues/584) -- Merge and minify js - Exception
   * [#585] (https://github.com/magento/magento2/pull/585) -- Add forgotten return statement
   * [#592] (https://github.com/magento/magento2/issues/592) -- Module name pattern
+  * [#618] (https://github.com/magento/magento2/issues/618) -- Fix of unit tests failure on Travis CI
 * Tax calculation updates:
   * Separate and display Weee line item totals from Tax
 * Fixed bugs:
@@ -30,18 +138,16 @@
   * Fixed an issue when configurable product was out of stock in Google Shopping while being in stock in the Magento backend
   * Fixed an issue when swipe gesture in menu widget was not supported on mobile
   * Fixed an issue when it was impossible to enter alpha-numeric zip code on the stage of  estimating shipping and tax rates
-  * Fixed an issue when it was impossible to edit gift card account
   * Fixed an issue when custom price was not applied when editing an order
-  * Fixed an issue when  items were  not returned to stock after unsuccessful order was placed
+  * Fixed an issue when items were not returned to stock after unsuccessful order was placed
   * Fixed an issue when error message appeared "Cannot save the credit memo” while creating credit memo
   * Fixed an issue when Catalog price rule was not shown for the product if price was less than a discount
 * Indexer implementation:
   * Implemented a new Stock indexer
   * Implemented a new EAV indexer
-  * Fixed failed L1 plan on phpunit 4.1.0
-  * Minor updates for integration test framework
-  * Split action controllers classes into action classes
-  * Added public MTF repository to the packagist.org
+* Minor updates for integration test framework
+* Split action controllers classes into action classes
+* Added public MTF repository to the packagist.org
 * Added the following functional tests:
   * Create Admin User
   * Create Category
diff --git a/app/code/Magento/AdminNotification/Block/System/Messages.php b/app/code/Magento/AdminNotification/Block/System/Messages.php
index 0800f20b6029ef2a32d92ec4ac1f4ad8f273d890..19695d3a9e4b5406efbe790fb9721cedfa2b39d9 100644
--- a/app/code/Magento/AdminNotification/Block/System/Messages.php
+++ b/app/code/Magento/AdminNotification/Block/System/Messages.php
@@ -17,7 +17,7 @@
  * Do not edit or add to this file if you wish to upgrade Magento to newer
  * versions in the future. If you wish to customize Magento for your
  * needs please refer to http://www.magentocommerce.com for more information.
- * 
+ *
  * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license   http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
@@ -129,7 +129,7 @@ class Messages extends \Magento\Backend\Block\Template
     }
 
     /**
-     * Initialize Syste,Message dialog widget
+     * Initialize system message dialog widget
      *
      * @return string
      */
diff --git a/app/code/Magento/Authorizenet/view/adminhtml/web/js/direct-post.js b/app/code/Magento/Authorizenet/view/adminhtml/web/js/direct-post.js
index a612fdfbe1d99caa2f6ddd7ec0f35f546c787d79..6dd6f9570e0bf38646352d39a04a0ca77b397a41 100644
--- a/app/code/Magento/Authorizenet/view/adminhtml/web/js/direct-post.js
+++ b/app/code/Magento/Authorizenet/view/adminhtml/web/js/direct-post.js
@@ -138,7 +138,7 @@ directPost.prototype = {
     loadOrderIframe : function() {
         if (this.orderRequestSent) {
             $(this.iframeId).hide();
-            var data = $('order-' + this.iframeId).contentWindow.document.body.innerHTML;
+            var data = $('order-' + this.iframeId).contentWindow.document.body.getElementsByTagName('pre')[0].innerHTML;
             this.saveAdminOrderSuccess(data);
             this.orderRequestSent = false;
         }
diff --git a/app/code/Magento/Authorizenet/view/frontend/templates/directpost/form.phtml b/app/code/Magento/Authorizenet/view/frontend/templates/directpost/form.phtml
index eaf45cebb7d11433dfa889adc9579a69032606c6..ae67dc82f22185655b393f436862e7d8e88388b3 100644
--- a/app/code/Magento/Authorizenet/view/frontend/templates/directpost/form.phtml
+++ b/app/code/Magento/Authorizenet/view/frontend/templates/directpost/form.phtml
@@ -91,7 +91,7 @@ $_orderUrl = $this->helper('Magento\Authorizenet\Helper\Data')->getPlaceOrderFro
                 <input type="number" title="<?php echo __('Card Verification Number') ?>" data-container="cc-cvv" class="input-text cvv" id="<?php echo $_code ?>_cc_cid" name="payment[cc_cid]" value="" data-validate='{required:true, "validate-cc-cvn":"#<?php echo $_code ?>_cc_type"}' autocomplete="off"/>
                 <?php $_content = '<img src=\"'.$this->getViewFileUrl('Magento_Checkout::cvv.gif').'\" alt=\"'.__('Card Verification Number Visual Reference').'\" title=\"'.__('Card Verification Number Visual Reference').'\" />'; ?>
                 <div class="note">
-                    <a href="#" id="directpost-cvv-what-is-this" class="action cvv" title="<?php echo __('What is this?') ?>" data-mage-init='{"tooltip": {"content": "<?php echo $_content ?>"}}'><span><?php echo __('What is this?') ?></span></a>
+                    <a href="#" id="directpost-cvv-what-is-this" class="action cvv" title="<?php echo $this->escapeHtml(__('What is this?'));?>" data-mage-init='{"tooltip": {"content": "<?php echo $_content ?>"}}'><span><?php echo __('What is this?') ?></span></a>
                 </div>
             </div>
         </div>
diff --git a/app/code/Magento/Backend/Controller/Adminhtml/System/AbstractConfig.php b/app/code/Magento/Backend/Controller/Adminhtml/System/AbstractConfig.php
index e3943fa0649df6950dc5e2984167f7e73e0bd57e..cfe6a95b4a697be4294e38e3c6c357ad45ee8c7a 100644
--- a/app/code/Magento/Backend/Controller/Adminhtml/System/AbstractConfig.php
+++ b/app/code/Magento/Backend/Controller/Adminhtml/System/AbstractConfig.php
@@ -27,8 +27,6 @@
  */
 namespace Magento\Backend\Controller\Adminhtml\System;
 
-use Magento\Framework\App\Action\NotFoundException;
-
 abstract class AbstractConfig extends \Magento\Backend\App\AbstractAction
 {
     /**
@@ -36,16 +34,25 @@ abstract class AbstractConfig extends \Magento\Backend\App\AbstractAction
      */
     protected $_configStructure;
 
+    /**
+     * @var ConfigSectionChecker
+     */
+    protected $_sectionChecker;
+
     /**
      * @param \Magento\Backend\App\Action\Context $context
      * @param \Magento\Backend\Model\Config\Structure $configStructure
+     * @param ConfigSectionChecker $sectionChecker
      */
     public function __construct(
         \Magento\Backend\App\Action\Context $context,
-        \Magento\Backend\Model\Config\Structure $configStructure
+        \Magento\Backend\Model\Config\Structure $configStructure,
+        ConfigSectionChecker $sectionChecker
     ) {
         parent::__construct($context);
         $this->_configStructure = $configStructure;
+        $this->_sectionChecker = $sectionChecker;
+
     }
 
     /**
@@ -56,12 +63,8 @@ abstract class AbstractConfig extends \Magento\Backend\App\AbstractAction
      */
     public function dispatch(\Magento\Framework\App\RequestInterface $request)
     {
-        $section = null;
         if (!$request->getParam('section')) {
-            $section = $this->_configStructure->getFirstSection();
-            $request->setParam('section', $section->getId());
-        } else {
-            $this->_isSectionAllowed($request->getParam('section'));
+            $request->setParam('section', $this->_configStructure->getFirstSection()->getId());
         }
         return parent::dispatch($request);
     }
@@ -73,33 +76,9 @@ abstract class AbstractConfig extends \Magento\Backend\App\AbstractAction
      */
     protected function _isAllowed()
     {
-        return $this->_authorization->isAllowed('Magento_Adminhtml::config');
-    }
-
-    /**
-     * Check if specified section allowed in ACL
-     *
-     * Will forward to deniedAction(), if not allowed.
-     *
-     * @param string $sectionId
-     * @throws \Exception
-     * @return bool
-     * @throws NotFoundException
-     */
-    protected function _isSectionAllowed($sectionId)
-    {
-        try {
-            if (false == $this->_configStructure->getElement($sectionId)->isAllowed()) {
-                throw new \Exception('');
-            }
-            return true;
-        } catch (\Zend_Acl_Exception $e) {
-            throw new NotFoundException();
-        } catch (\Exception $e) {
-            $this->deniedAction();
-            $this->_actionFlag->set('', self::FLAG_NO_DISPATCH, true);
-            return false;
-        }
+        $sectionId = $this->_request->getParam('section');
+        return $this->_authorization->isAllowed('Magento_Adminhtml::config')
+            || $this->_configStructure->getElement($sectionId)->isAllowed();
     }
 
     /**
diff --git a/app/code/Magento/Backend/Controller/Adminhtml/System/Config/AbstractScopeConfig.php b/app/code/Magento/Backend/Controller/Adminhtml/System/Config/AbstractScopeConfig.php
new file mode 100644
index 0000000000000000000000000000000000000000..5bec8035aa9f01fbd7c8bbb5207921caf2e568ba
--- /dev/null
+++ b/app/code/Magento/Backend/Controller/Adminhtml/System/Config/AbstractScopeConfig.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+ 
+namespace Magento\Backend\Controller\Adminhtml\System\Config;
+
+use Magento\Backend\Controller\Adminhtml\System\ConfigSectionChecker;
+
+abstract class AbstractScopeConfig extends \Magento\Backend\Controller\Adminhtml\System\AbstractConfig
+{
+    /**
+     * @var \Magento\Backend\Model\Config
+     */
+    protected $_backendConfig;
+
+    /**
+     * @param \Magento\Backend\App\Action\Context $context
+     * @param \Magento\Backend\Model\Config\Structure $configStructure
+     * @param ConfigSectionChecker $sectionChecker
+     * @param \Magento\Backend\Model\Config $backendConfig
+     */
+    public function __construct(
+        \Magento\Backend\App\Action\Context $context,
+        \Magento\Backend\Model\Config\Structure $configStructure,
+        ConfigSectionChecker $sectionChecker,
+        \Magento\Backend\Model\Config $backendConfig
+    ) {
+        $this->_backendConfig = $backendConfig;
+        parent::__construct($context, $configStructure, $sectionChecker);
+    }
+
+    /**
+     * Sets scope for backend config
+     *
+     * @param string $sectionId
+     * @return bool
+     */
+    protected function isSectionAllowed($sectionId)
+    {
+        $website = $this->getRequest()->getParam('website');
+        $store = $this->getRequest()->getParam('store');
+        if ($store) {
+            $this->_backendConfig->setStore($store);
+        } elseif ($website) {
+            $this->_backendConfig->setWebsite($website);
+        }
+        return parent::isSectionAllowed($sectionId);
+    }
+}
diff --git a/app/code/Magento/Backend/Controller/Adminhtml/System/Config/Edit.php b/app/code/Magento/Backend/Controller/Adminhtml/System/Config/Edit.php
index fb560afbdb0335662f5518e0b51021817a94c39f..f6d54e520c9fca7a11494477d269889d81ed289a 100644
--- a/app/code/Magento/Backend/Controller/Adminhtml/System/Config/Edit.php
+++ b/app/code/Magento/Backend/Controller/Adminhtml/System/Config/Edit.php
@@ -24,7 +24,7 @@
  */
 namespace Magento\Backend\Controller\Adminhtml\System\Config;
 
-class Edit extends \Magento\Backend\Controller\Adminhtml\System\AbstractConfig
+class Edit extends AbstractScopeConfig
 {
     /**
      * Edit configuration section
diff --git a/app/code/Magento/Backend/Controller/Adminhtml/System/Config/Index.php b/app/code/Magento/Backend/Controller/Adminhtml/System/Config/Index.php
index 157a019c8fa0fd507b7e36cd9836a7fd523146ac..1b5d451e51cdcc22ed21f99d0c15626de640e1ed 100644
--- a/app/code/Magento/Backend/Controller/Adminhtml/System/Config/Index.php
+++ b/app/code/Magento/Backend/Controller/Adminhtml/System/Config/Index.php
@@ -24,7 +24,7 @@
  */
 namespace Magento\Backend\Controller\Adminhtml\System\Config;
 
-class Index extends \Magento\Backend\Controller\Adminhtml\System\AbstractConfig
+class Index extends AbstractScopeConfig
 {
     /**
      * Index action
diff --git a/app/code/Magento/Backend/Controller/Adminhtml/System/Config/Save.php b/app/code/Magento/Backend/Controller/Adminhtml/System/Config/Save.php
index 2c9ca838c87bcb9626e658c4787b3707aaa1cfc1..a0cffac49122b43ee65725e23a548d8e9f9090a4 100644
--- a/app/code/Magento/Backend/Controller/Adminhtml/System/Config/Save.php
+++ b/app/code/Magento/Backend/Controller/Adminhtml/System/Config/Save.php
@@ -53,6 +53,7 @@ class Save extends AbstractConfig
     /**
      * @param \Magento\Backend\App\Action\Context $context
      * @param \Magento\Backend\Model\Config\Structure $configStructure
+     * @param \Magento\Backend\Controller\Adminhtml\System\ConfigSectionChecker $sectionChecker
      * @param \Magento\Backend\Model\Config\Factory $configFactory
      * @param \Magento\Framework\Cache\FrontendInterface $cache
      * @param \Magento\Framework\Stdlib\String $string
@@ -60,11 +61,12 @@ class Save extends AbstractConfig
     public function __construct(
         \Magento\Backend\App\Action\Context $context,
         \Magento\Backend\Model\Config\Structure $configStructure,
+        \Magento\Backend\Controller\Adminhtml\System\ConfigSectionChecker $sectionChecker,
         \Magento\Backend\Model\Config\Factory $configFactory,
         \Magento\Framework\Cache\FrontendInterface $cache,
         \Magento\Framework\Stdlib\String $string
     ) {
-        parent::__construct($context, $configStructure);
+        parent::__construct($context, $configStructure, $sectionChecker);
         $this->_configFactory = $configFactory;
         $this->_cache = $cache;
         $this->string = $string;
@@ -160,10 +162,6 @@ class Save extends AbstractConfig
     public function execute()
     {
         try {
-            if (false == $this->_isSectionAllowed($this->getRequest()->getParam('section'))) {
-                throw new \Exception(__('This section is not allowed.'));
-            }
-
             // custom save logic
             $this->_saveSection();
             $section = $this->getRequest()->getParam('section');
diff --git a/app/code/Magento/Backend/Controller/Adminhtml/System/Config/State.php b/app/code/Magento/Backend/Controller/Adminhtml/System/Config/State.php
index a43679ee9e6dfa0994ed3b355b0ef69b11d6780d..ed7a44aff92f9eab806518f9a32e368ce0381d95 100644
--- a/app/code/Magento/Backend/Controller/Adminhtml/System/Config/State.php
+++ b/app/code/Magento/Backend/Controller/Adminhtml/System/Config/State.php
@@ -24,7 +24,7 @@
  */
 namespace Magento\Backend\Controller\Adminhtml\System\Config;
 
-class State extends \Magento\Backend\Controller\Adminhtml\System\AbstractConfig
+class State extends AbstractScopeConfig
 {
     /**
      * Save fieldset state through AJAX
diff --git a/app/code/Magento/Backend/Controller/Adminhtml/System/ConfigSectionChecker.php b/app/code/Magento/Backend/Controller/Adminhtml/System/ConfigSectionChecker.php
new file mode 100644
index 0000000000000000000000000000000000000000..6e3c320d5203151a66fe3a242bfce16e16780a4f
--- /dev/null
+++ b/app/code/Magento/Backend/Controller/Adminhtml/System/ConfigSectionChecker.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+ 
+namespace Magento\Backend\Controller\Adminhtml\System;
+
+use Magento\Framework\App\Action\NotFoundException;
+
+class ConfigSectionChecker
+{
+    /**
+     * @var \Magento\Backend\Model\Config\Structure
+     */
+    protected $_configStructure;
+
+    /**
+     * @param \Magento\Backend\Model\Config\Structure $configStructure
+     */
+    public function __construct(\Magento\Backend\Model\Config\Structure $configStructure)
+    {
+        $this->_configStructure = $configStructure;
+    }
+
+    /**
+     * Check if specified section allowed in ACL
+     *
+     * Will forward to deniedAction(), if not allowed.
+     *
+     * @param string $sectionId
+     * @throws \Exception
+     * @return bool
+     * @throws NotFoundException
+     */
+    public function isSectionAllowed($sectionId)
+    {
+        try {
+            if (false == $this->_configStructure->getElement($sectionId)->isAllowed()) {
+                throw new \Exception('');
+            }
+            return true;
+        } catch (\Zend_Acl_Exception $e) {
+            throw new NotFoundException();
+        } catch (\Exception $e) {
+            return false;
+        }
+    }
+}
diff --git a/app/code/Magento/Backend/Model/Config.php b/app/code/Magento/Backend/Model/Config.php
index 5bee720ba2d6bb516793ee73cb6a246a180db907..4bf70b7a933d523b006ae5f969fe2b20adf3e23c 100644
--- a/app/code/Magento/Backend/Model/Config.php
+++ b/app/code/Magento/Backend/Model/Config.php
@@ -383,12 +383,12 @@ class Config extends \Magento\Framework\Object
             $scope = 'stores';
             $store = $this->_storeManager->getStore($this->getStore());
             $scopeId = (int)$store->getId();
-            $scopeCode = $this->getStore();
+            $scopeCode = $store->getCode();
         } elseif ($this->getWebsite()) {
             $scope = 'websites';
             $website = $this->_storeManager->getWebsite($this->getWebsite());
             $scopeId = (int)$website->getId();
-            $scopeCode = $this->getWebsite();
+            $scopeCode = $website->getCode();
         } else {
             $scope = 'default';
             $scopeId = 0;
diff --git a/app/code/Magento/Backend/etc/config.xml b/app/code/Magento/Backend/etc/config.xml
index 334c5434d44d1ec1f161134f949dd4320669a67c..1a88e36aea2c3d6e4f7e8f198b0a96381b049755 100644
--- a/app/code/Magento/Backend/etc/config.xml
+++ b/app/code/Magento/Backend/etc/config.xml
@@ -55,6 +55,11 @@
                 </input_types>
             </validator_data>
         </general>
+        <web>
+            <seo>
+                <use_rewrites>0</use_rewrites>
+            </seo>
+        </web>
     </default>
     <stores>
         <admin>
diff --git a/app/code/Magento/Backend/view/adminhtml/templates/widget/grid.phtml b/app/code/Magento/Backend/view/adminhtml/templates/widget/grid.phtml
index eecc6ecb9c8083f6819f2096945ebf9931b72177..2a0da74a661ab296c772469dd87ec03a17a382dd 100644
--- a/app/code/Magento/Backend/view/adminhtml/templates/widget/grid.phtml
+++ b/app/code/Magento/Backend/view/adminhtml/templates/widget/grid.phtml
@@ -46,7 +46,7 @@ $numColumns = sizeof($this->getColumns());
         </div>
     <?php endif ?>
 
-    <div id="<?php echo $this->getId() ?>">
+    <div id="<?php echo $this->getId() ?>" data-grid-id="<?php echo $this->getId() ?>">
         <?php else: ?>
             <?php echo $this->getLayout()->getMessagesBlock()->getGroupedHtml() ?>
         <?php endif; ?>
diff --git a/app/code/Magento/Bundle/Block/Adminhtml/Sales/Order/Items/Renderer.php b/app/code/Magento/Bundle/Block/Adminhtml/Sales/Order/Items/Renderer.php
index 9ff68dfb5cb5f666143b392e5dc88aa8a27a7bba..029bd9120999a992071b91b06fd24065624ac5cf 100644
--- a/app/code/Magento/Bundle/Block/Adminhtml/Sales/Order/Items/Renderer.php
+++ b/app/code/Magento/Bundle/Block/Adminhtml/Sales/Order/Items/Renderer.php
@@ -49,16 +49,16 @@ class Renderer extends \Magento\Sales\Block\Adminhtml\Items\Renderer\DefaultRend
     }
 
     /**
-     * Getting all available childs for Invoice, Shipmen or Creditmemo item
+     * Getting all available children for Invoice, Shipment or CreditMemo item
      *
      * @param \Magento\Framework\Object $item
-     * @return array
+     * @return array|null
      */
     public function getChilds($item)
     {
         $itemsArray = array();
 
-        $items = false;
+        $items = null;
         if ($item instanceof \Magento\Sales\Model\Order\Invoice\Item) {
             $items = $item->getInvoice()->getAllItems();
         } elseif ($item instanceof \Magento\Sales\Model\Order\Shipment\Item) {
@@ -99,33 +99,21 @@ class Renderer extends \Magento\Sales\Block\Adminhtml\Items\Renderer\DefaultRend
             if ($parentItem) {
                 $options = $parentItem->getProductOptions();
                 if ($options) {
-                    if (isset($options['shipment_type'])
-                        && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY
-                    ) {
-                        return true;
-                    } else {
-                        return false;
-                    }
+                    return (isset($options['shipment_type'])
+                        && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY);
                 }
             } else {
                 $options = $item->getProductOptions();
                 if ($options) {
-                    if (isset($options['shipment_type'])
-                        && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY
-                    ) {
-                        return false;
-                    } else {
-                        return true;
-                    }
+                    return !(isset($options['shipment_type'])
+                        && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY);
                 }
             }
         }
 
         $options = $this->getOrderItem()->getProductOptions();
         if ($options) {
-            if (isset($options['shipment_type'])
-                && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY
-            ) {
+            if (isset($options['shipment_type']) && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY) {
                 return true;
             }
         }
@@ -146,24 +134,14 @@ class Renderer extends \Magento\Sales\Block\Adminhtml\Items\Renderer\DefaultRend
             if ($parentItem) {
                 $options = $parentItem->getProductOptions();
                 if ($options) {
-                    if (isset($options['product_calculations'])
-                        && $options['product_calculations'] == AbstractType::CALCULATE_CHILD
-                    ) {
-                        return true;
-                    } else {
-                        return false;
-                    }
+                    return (isset($options['product_calculations'])
+                        && $options['product_calculations'] == AbstractType::CALCULATE_CHILD);
                 }
             } else {
                 $options = $item->getProductOptions();
                 if ($options) {
-                    if (isset($options['product_calculations'])
-                        && $options['product_calculations'] == AbstractType::CALCULATE_CHILD
-                    ) {
-                        return false;
-                    } else {
-                        return true;
-                    }
+                    return !(isset($options['product_calculations'])
+                        && $options['product_calculations'] == AbstractType::CALCULATE_CHILD);
                 }
             }
         }
diff --git a/app/code/Magento/Bundle/Block/Adminhtml/Sales/Order/View/Items/Renderer.php b/app/code/Magento/Bundle/Block/Adminhtml/Sales/Order/View/Items/Renderer.php
index 070b02878a5c3c030c1620885e3c565edfa962d6..90ea6e9622826d5a4246f2006f5732b504fef881 100644
--- a/app/code/Magento/Bundle/Block/Adminhtml/Sales/Order/View/Items/Renderer.php
+++ b/app/code/Magento/Bundle/Block/Adminhtml/Sales/Order/View/Items/Renderer.php
@@ -59,33 +59,21 @@ class Renderer extends \Magento\Sales\Block\Adminhtml\Order\View\Items\Renderer\
             if ($parentItem) {
                 $options = $parentItem->getProductOptions();
                 if ($options) {
-                    if (isset($options['shipment_type'])
-                        && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY
-                    ) {
-                        return true;
-                    } else {
-                        return false;
-                    }
+                    return (isset($options['shipment_type'])
+                        && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY);
                 }
             } else {
                 $options = $item->getProductOptions();
                 if ($options) {
-                    if (isset($options['shipment_type'])
-                        && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY
-                    ) {
-                        return false;
-                    } else {
-                        return true;
-                    }
+                    return !(isset($options['shipment_type'])
+                        && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY);
                 }
             }
         }
 
-        $options = $this->getOrderItem()->getProductOptions();
+        $options = $this->getItem()->getProductOptions();
         if ($options) {
-            if (isset($options['shipment_type'])
-                && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY
-            ) {
+            if (isset($options['shipment_type']) && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY) {
                 return true;
             }
         }
@@ -103,24 +91,14 @@ class Renderer extends \Magento\Sales\Block\Adminhtml\Order\View\Items\Renderer\
             if ($parentItem) {
                 $options = $parentItem->getProductOptions();
                 if ($options) {
-                    if (isset($options['product_calculations'])
-                        && $options['product_calculations'] == AbstractType::CALCULATE_CHILD
-                    ) {
-                        return true;
-                    } else {
-                        return false;
-                    }
+                    return (isset($options['product_calculations'])
+                        && $options['product_calculations'] == AbstractType::CALCULATE_CHILD);
                 }
             } else {
                 $options = $item->getProductOptions();
                 if ($options) {
-                    if (isset($options['product_calculations'])
-                        && $options['product_calculations'] == AbstractType::CALCULATE_CHILD
-                    ) {
-                        return false;
-                    } else {
-                        return true;
-                    }
+                    return !(isset($options['product_calculations'])
+                        && $options['product_calculations'] == AbstractType::CALCULATE_CHILD);
                 }
             }
         }
diff --git a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php
index 5eb6faa3ba8dfdb0ccd33f8a8739e23fdff5a0f8..e9438dd2a5cd0038936b82cc66ae7396dbd52707 100644
--- a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php
+++ b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php
@@ -24,7 +24,7 @@
 namespace Magento\Bundle\Block\Catalog\Product\View\Type;
 
 use Magento\Framework\Pricing\PriceCurrencyInterface;
-use Magento\Tax\Model\Calculation;
+use Magento\Tax\Service\V1\TaxCalculationServiceInterface;
 
 /**
  * Catalog bundle product info block
@@ -46,9 +46,9 @@ class Bundle extends \Magento\Catalog\Block\Product\View\AbstractView
      * @var array
      */
     protected $mapping = [
-        Calculation::CALC_UNIT_BASE => self::UNIT_ROUNDING,
-        Calculation::CALC_ROW_BASE => self::ROW_ROUNDING,
-        Calculation::CALC_TOTAL_BASE => self::TOTAL_ROUNDING,
+        TaxCalculationServiceInterface::CALC_UNIT_BASE => self::UNIT_ROUNDING,
+        TaxCalculationServiceInterface::CALC_ROW_BASE => self::ROW_ROUNDING,
+        TaxCalculationServiceInterface::CALC_TOTAL_BASE => self::TOTAL_ROUNDING,
     ];
 
     /**
diff --git a/app/code/Magento/Bundle/Block/Sales/Order/Items/Renderer.php b/app/code/Magento/Bundle/Block/Sales/Order/Items/Renderer.php
index ec6a182465ad5a9626fa360d603213c855f2e7a2..ac0fb075fd5c5f0c48e5228a4806a63c32a72329 100644
--- a/app/code/Magento/Bundle/Block/Sales/Order/Items/Renderer.php
+++ b/app/code/Magento/Bundle/Block/Sales/Order/Items/Renderer.php
@@ -23,6 +23,8 @@
  */
 namespace Magento\Bundle\Block\Sales\Order\Items;
 
+use \Magento\Catalog\Model\Product\Type\AbstractType;
+
 /**
  * Order item render block
  *
@@ -40,40 +42,25 @@ class Renderer extends \Magento\Sales\Block\Order\Item\Renderer\DefaultRenderer
             if ($item->getOrderItem()) {
                 $item = $item->getOrderItem();
             }
-            if ($parentItem = $item->getParentItem()) {
-                if ($options = $parentItem->getProductOptions()) {
-                    if (isset(
-                        $options['shipment_type']
-                    ) &&
-                        $options['shipment_type'] ==
-                        \Magento\Catalog\Model\Product\Type\AbstractType::SHIPMENT_SEPARATELY
-                    ) {
-                        return true;
-                    } else {
-                        return false;
-                    }
+            $parentItem = $item->getParentItem();
+            if ($parentItem) {
+                $options = $parentItem->getProductOptions();
+                if ($options) {
+                    return (isset($options['shipment_type'])
+                        && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY);
                 }
             } else {
-                if ($options = $item->getProductOptions()) {
-                    if (isset(
-                        $options['shipment_type']
-                    ) &&
-                        $options['shipment_type'] ==
-                        \Magento\Catalog\Model\Product\Type\AbstractType::SHIPMENT_SEPARATELY
-                    ) {
-                        return false;
-                    } else {
-                        return true;
-                    }
+                $options = $item->getProductOptions();
+                if ($options) {
+                    return !(isset($options['shipment_type'])
+                        && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY);
                 }
             }
         }
 
-        if ($options = $this->getOrderItem()->getProductOptions()) {
-            if (isset(
-                $options['shipment_type']
-            ) && $options['shipment_type'] == \Magento\Catalog\Model\Product\Type\AbstractType::SHIPMENT_SEPARATELY
-            ) {
+        $options = $this->getOrderItem()->getProductOptions();
+        if ($options) {
+            if (isset($options['shipment_type']) && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY) {
                 return true;
             }
         }
@@ -90,39 +77,26 @@ class Renderer extends \Magento\Sales\Block\Order\Item\Renderer\DefaultRenderer
             if ($item->getOrderItem()) {
                 $item = $item->getOrderItem();
             }
-            if ($parentItem = $item->getParentItem()) {
-                if ($options = $parentItem->getProductOptions()) {
-                    if (isset(
-                        $options['product_calculations']
-                    ) &&
-                        $options['product_calculations'] ==
-                        \Magento\Catalog\Model\Product\Type\AbstractType::CALCULATE_CHILD
-                    ) {
-                        return true;
-                    } else {
-                        return false;
-                    }
+            $parentItem = $item->getParentItem();
+            if ($parentItem) {
+                $options = $parentItem->getProductOptions();
+                if ($options) {
+                    return (isset($options['product_calculations'])
+                        && $options['product_calculations'] == AbstractType::CALCULATE_CHILD);
                 }
             } else {
-                if ($options = $item->getProductOptions()) {
-                    if (isset(
-                        $options['product_calculations']
-                    ) &&
-                        $options['product_calculations'] ==
-                        \Magento\Catalog\Model\Product\Type\AbstractType::CALCULATE_CHILD
-                    ) {
-                        return false;
-                    } else {
-                        return true;
-                    }
+                $options = $item->getProductOptions();
+                if ($options) {
+                    return !(isset($options['product_calculations'])
+                        && $options['product_calculations'] == AbstractType::CALCULATE_CHILD);
                 }
             }
         }
 
-        if ($options = $this->getOrderItem()->getProductOptions()) {
-            if (isset(
-                $options['product_calculations']
-            ) && $options['product_calculations'] == \Magento\Catalog\Model\Product\Type\AbstractType::CALCULATE_CHILD
+        $options = $this->getOrderItem()->getProductOptions();
+        if ($options) {
+            if (isset($options['product_calculations'])
+                && $options['product_calculations'] == AbstractType::CALCULATE_CHILD
             ) {
                 return true;
             }
@@ -154,49 +128,45 @@ class Renderer extends \Magento\Sales\Block\Order\Item\Renderer\DefaultRenderer
     public function getValueHtml($item)
     {
         if ($attributes = $this->getSelectionAttributes($item)) {
-            return sprintf(
-                '%d',
-                $attributes['qty']
-            ) . ' x ' . $this->escapeHtml(
-                $item->getName()
-            ) . " " . $this->getOrder()->formatPrice(
-                $attributes['price']
-            );
+            return sprintf('%d', $attributes['qty']) . ' x ' . $this->escapeHtml($item->getName()) . " "
+                . $this->getOrder()->formatPrice($attributes['price']);
         } else {
             return $this->escapeHtml($item->getName());
         }
     }
 
     /**
-     * Getting all available childs for Invoice, Shipmen or Creditmemo item
+     * Getting all available children for Invoice, Shipment or CreditMemo item
      *
      * @param \Magento\Framework\Object $item
      * @return array
      */
     public function getChilds($item)
     {
-        $_itemsArray = array();
+        $itemsArray = array();
 
+        $items = null;
         if ($item instanceof \Magento\Sales\Model\Order\Invoice\Item) {
-            $_items = $item->getInvoice()->getAllItems();
-        } else if ($item instanceof \Magento\Sales\Model\Order\Shipment\Item) {
-            $_items = $item->getShipment()->getAllItems();
-        } else if ($item instanceof \Magento\Sales\Model\Order\Creditmemo\Item) {
-            $_items = $item->getCreditmemo()->getAllItems();
+            $items = $item->getInvoice()->getAllItems();
+        } elseif ($item instanceof \Magento\Sales\Model\Order\Shipment\Item) {
+            $items = $item->getShipment()->getAllItems();
+        } elseif ($item instanceof \Magento\Sales\Model\Order\Creditmemo\Item) {
+            $items = $item->getCreditmemo()->getAllItems();
         }
 
-        if ($_items) {
-            foreach ($_items as $_item) {
-                if ($parentItem = $_item->getOrderItem()->getParentItem()) {
-                    $_itemsArray[$parentItem->getId()][$_item->getOrderItemId()] = $_item;
+        if ($items) {
+            foreach ($items as $value) {
+                $parentItem = $value->getOrderItem()->getParentItem();
+                if ($parentItem) {
+                    $itemsArray[$parentItem->getId()][$value->getOrderItemId()] = $value;
                 } else {
-                    $_itemsArray[$_item->getOrderItem()->getId()][$_item->getOrderItemId()] = $_item;
+                    $itemsArray[$value->getOrderItem()->getId()][$value->getOrderItemId()] = $value;
                 }
             }
         }
 
-        if (isset($_itemsArray[$item->getOrderItem()->getId()])) {
-            return $_itemsArray[$item->getOrderItem()->getId()];
+        if (isset($itemsArray[$item->getOrderItem()->getId()])) {
+            return $itemsArray[$item->getOrderItem()->getId()];
         } else {
             return null;
         }
diff --git a/app/code/Magento/Bundle/Helper/Catalog/Product/Configuration.php b/app/code/Magento/Bundle/Helper/Catalog/Product/Configuration.php
index 3e19a638c430ef5cc4cec43fbecfe3c76ca4badb..45ce20d519b91fd83f7e1b97858220bf313db2c7 100644
--- a/app/code/Magento/Bundle/Helper/Catalog/Product/Configuration.php
+++ b/app/code/Magento/Bundle/Helper/Catalog/Product/Configuration.php
@@ -28,7 +28,7 @@ use Magento\Catalog\Model\Product\Configuration\Item\ItemInterface;
 use Magento\Framework\App\Helper\AbstractHelper;
 
 /**
- * Helper for fetching properties by product configurational item
+ * Helper for fetching properties by product configuration item
  */
 class Configuration extends AbstractHelper implements ConfigurationInterface
 {
@@ -37,7 +37,7 @@ class Configuration extends AbstractHelper implements ConfigurationInterface
      *
      * @var \Magento\Core\Helper\Data
      */
-    protected $_coreData;
+    protected $coreData;
 
     /**
      * Catalog product configuration
@@ -47,9 +47,11 @@ class Configuration extends AbstractHelper implements ConfigurationInterface
     protected $productConfiguration;
 
     /**
+     * Escaper
+     *
      * @var \Magento\Framework\Escaper
      */
-    protected $_escaper;
+    protected $escaper;
 
     /**
      * @param \Magento\Framework\App\Helper\Context $context
@@ -64,8 +66,8 @@ class Configuration extends AbstractHelper implements ConfigurationInterface
         \Magento\Framework\Escaper $escaper
     ) {
         $this->productConfiguration = $productConfiguration;
-        $this->_coreData = $coreData;
-        $this->_escaper = $escaper;
+        $this->coreData = $coreData;
+        $this->escaper = $escaper;
         parent::__construct($context);
     }
 
@@ -74,10 +76,9 @@ class Configuration extends AbstractHelper implements ConfigurationInterface
      *
      * @param \Magento\Catalog\Model\Product $product
      * @param int $selectionId
-     *
      * @return float
      */
-    public function getSelectionQty($product, $selectionId)
+    public function getSelectionQty(\Magento\Catalog\Model\Product $product, $selectionId)
     {
         $selectionQty = $product->getCustomOption('selection_qty_' . $selectionId);
         if ($selectionQty) {
@@ -91,19 +92,21 @@ class Configuration extends AbstractHelper implements ConfigurationInterface
      *
      * @param ItemInterface $item
      * @param \Magento\Catalog\Model\Product $selectionProduct
-     *
      * @return float
      */
-    public function getSelectionFinalPrice(ItemInterface $item, $selectionProduct)
+    public function getSelectionFinalPrice(ItemInterface $item, \Magento\Catalog\Model\Product $selectionProduct)
     {
         $selectionProduct->unsetData('final_price');
-        /** @var \Magento\Bundle\Model\Product\Price $priceModel */
-        $priceModel = $item->getProduct()->getPriceModel();
-        return $priceModel->getSelectionFinalTotalPrice(
-            $item->getProduct(),
+
+        $product = $item->getProduct();
+        /** @var \Magento\Bundle\Model\Product\Price $price */
+        $price = $product->getPriceModel();
+
+        return $price->getSelectionFinalTotalPrice(
+            $product,
             $selectionProduct,
-            $item->getQty() * 1,
-            $this->getSelectionQty($item->getProduct(), $selectionProduct->getSelectionId()),
+            $item->getQty(),
+            $this->getSelectionQty($product, $selectionProduct->getSelectionId()),
             false,
             true
         );
@@ -151,11 +154,10 @@ class Configuration extends AbstractHelper implements ConfigurationInterface
                         foreach ($bundleSelections as $bundleSelection) {
                             $qty = $this->getSelectionQty($product, $bundleSelection->getSelectionId()) * 1;
                             if ($qty) {
-                                $option['value'][] = $qty . ' x ' . $this->_escaper->escapeHtml(
-                                    $bundleSelection->getName()
-                                ) . ' ' . $this->_coreData->currency(
-                                    $this->getSelectionFinalPrice($item, $bundleSelection)
-                                );
+                                $option['value'][] = $qty . ' x '
+                                    . $this->escaper->escapeHtml($bundleSelection->getName())
+                                    . ' '
+                                    . $this->coreData->currency($this->getSelectionFinalPrice($item, $bundleSelection));
                             }
                         }
 
diff --git a/app/code/Magento/Bundle/Helper/Data.php b/app/code/Magento/Bundle/Helper/Data.php
index a6b9c76ad7b3c99845698dbf5cb50c6e2d0b2409..364e95e4c8e7bfc5f318974361f7d5ce6020ab76 100644
--- a/app/code/Magento/Bundle/Helper/Data.php
+++ b/app/code/Magento/Bundle/Helper/Data.php
@@ -33,7 +33,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
     /**
      * @var \Magento\Catalog\Model\ProductTypes\ConfigInterface
      */
-    protected $_config;
+    protected $config;
 
     /**
      * @param \Magento\Framework\App\Helper\Context $context
@@ -43,7 +43,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
         \Magento\Framework\App\Helper\Context $context,
         \Magento\Catalog\Model\ProductTypes\ConfigInterface $config
     ) {
-        $this->_config = $config;
+        $this->config = $config;
         parent::__construct($context);
     }
 
@@ -54,7 +54,8 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
      */
     public function getAllowedSelectionTypes()
     {
-        $configData = $this->_config->getType('bundle');
-        return isset($configData['allowed_selection_types']) ? $configData['allowed_selection_types'] : array();
+        $configData = $this->config->getType(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE);
+
+        return isset($configData['allowed_selection_types']) ? $configData['allowed_selection_types'] : [];
     }
 }
diff --git a/app/code/Magento/Bundle/Model/Option.php b/app/code/Magento/Bundle/Model/Option.php
index 73df7196d863c53c9f19fa02af6848f7f3bc3f34..6ea371a737ce33580234b3a008895c6328bf9345 100644
--- a/app/code/Magento/Bundle/Model/Option.php
+++ b/app/code/Magento/Bundle/Model/Option.php
@@ -27,23 +27,23 @@ namespace Magento\Bundle\Model;
  * Bundle Option Model
  *
  * @method int getParentId()
- * @method \Magento\Bundle\Model\Option setParentId(int $value)
- * @method int getRequired()
- * @method \Magento\Bundle\Model\Option setRequired(int $value)
  * @method int getPosition()
- * @method \Magento\Bundle\Model\Option setPosition(int $value)
+ * @method int getRequired()
+ * @method null|\Magento\Catalog\Model\Product[] getSelections()
  * @method string getType()
- * @method \Magento\Bundle\Model\Option setType(string $value)
- * @method \Magento\Catalog\Model\Product[] getSelections()
+ * @method Option setParentId(int $value)
+ * @method Option setPosition(int $value)
+ * @method Option setRequired(int $value)
+ * @method Option setType(string $value)
  */
 class Option extends \Magento\Framework\Model\AbstractModel
 {
     /**
      * Default selection object
      *
-     * @var Selection
+     * @var \Magento\Catalog\Model\Product|null
      */
-    protected $_defaultSelection = null;
+    protected $defaultSelection = null;
 
     /**
      * Initialize resource model
@@ -59,18 +59,14 @@ class Option extends \Magento\Framework\Model\AbstractModel
     /**
      * Add selection to option
      *
-     * @param Selection $selection
-     * @return $this|false
+     * @param \Magento\Catalog\Model\Product $selection
+     * @return void
      */
-    public function addSelection($selection)
+    public function addSelection(\Magento\Catalog\Model\Product $selection)
     {
-        if (!$selection) {
-            return false;
-        }
-        $selections = $this->getDataSetDefault('selections', array());
+        $selections = $this->getDataSetDefault('selections', []);
         $selections[] = $selection;
         $this->setSelections($selections);
-        return $this;
     }
 
     /**
@@ -80,35 +76,35 @@ class Option extends \Magento\Framework\Model\AbstractModel
      */
     public function isSaleable()
     {
-        $saleable = 0;
-        if ($this->getSelections()) {
-            foreach ($this->getSelections() as $selection) {
+        $saleable = false;
+        $selections = $this->getSelections();
+        if ($selections) {
+            foreach ($selections as $selection) {
                 if ($selection->isSaleable()) {
-                    $saleable++;
+                    $saleable = true;
+                    break;
                 }
             }
-            return (bool) $saleable;
-        } else {
-            return false;
         }
+        return $saleable;
     }
 
     /**
      * Retrieve default Selection object
      *
-     * @return Selection
+     * @return \Magento\Catalog\Model\Product|null
      */
     public function getDefaultSelection()
     {
-        if (!$this->_defaultSelection && $this->getSelections()) {
+        if (!$this->defaultSelection && $this->getSelections()) {
             foreach ($this->getSelections() as $selection) {
                 if ($selection->getIsDefault()) {
-                    $this->_defaultSelection = $selection;
+                    $this->defaultSelection = $selection;
                     break;
                 }
             }
         }
-        return $this->_defaultSelection;
+        return $this->defaultSelection;
     }
 
     /**
@@ -118,11 +114,7 @@ class Option extends \Magento\Framework\Model\AbstractModel
      */
     public function isMultiSelection()
     {
-        if ($this->getType() == 'checkbox' || $this->getType() == 'multi') {
-            return true;
-        } else {
-            return false;
-        }
+        return $this->getType() == 'checkbox' || $this->getType() == 'multi';
     }
 
     /**
@@ -141,15 +133,17 @@ class Option extends \Magento\Framework\Model\AbstractModel
      * Return selection by it's id
      *
      * @param int $selectionId
-     * @return Selection|false
+     * @return \Magento\Catalog\Model\Product|null
      */
     public function getSelectionById($selectionId)
     {
-        foreach ($this->getSelections() as $option) {
-            if ($option->getSelectionId() == $selectionId) {
-                return $option;
+        $foundSelection = null;
+        foreach ($this->getSelections() as $selection) {
+            if ($selection->getSelectionId() == $selectionId) {
+                $foundSelection = $selection;
+                break;
             }
         }
-        return false;
+        return $foundSelection;
     }
 }
diff --git a/app/code/Magento/Bundle/Model/Plugin/PriceBackend.php b/app/code/Magento/Bundle/Model/Plugin/PriceBackend.php
index 61dd8091c80b2c5636d7669e79cf527ce8558b01..1a70af60d6375a3334da66c6bfdb27ccee5b481e 100644
--- a/app/code/Magento/Bundle/Model/Plugin/PriceBackend.php
+++ b/app/code/Magento/Bundle/Model/Plugin/PriceBackend.php
@@ -32,7 +32,7 @@ class PriceBackend
 {
     /**
      * @param \Magento\Catalog\Model\Product\Attribute\Backend\Price $subject
-     * @param Closure $proceed
+     * @param \Closure $proceed
      * @param \Magento\Catalog\Model\Product $product
      * @return bool
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
@@ -42,7 +42,9 @@ class PriceBackend
         \Closure $proceed,
         \Magento\Catalog\Model\Product $product
     ) {
-        if ($product->getPriceType() == \Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC) {
+        if ($product->getTypeId() == \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE
+            && $product->getPriceType() == \Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC
+        ) {
             return true;
         } else {
             return $proceed($product);
diff --git a/app/code/Magento/Bundle/Model/Product/Attribute/Source/Price/View.php b/app/code/Magento/Bundle/Model/Product/Attribute/Source/Price/View.php
index c817d9a99928b6e0214d13d5bc66863f59db6360..36c4b861430a6a2b13f9bcf4c7f00af713b4f093 100644
--- a/app/code/Magento/Bundle/Model/Product/Attribute/Source/Price/View.php
+++ b/app/code/Magento/Bundle/Model/Product/Attribute/Source/Price/View.php
@@ -23,6 +23,9 @@
  */
 namespace Magento\Bundle\Model\Product\Attribute\Source\Price;
 
+use Magento\Eav\Model\Resource\Entity\Attribute\OptionFactory;
+use Magento\Framework\DB\Ddl\Table;
+
 /**
  * Bundle Price View Attribute Renderer
  *
@@ -31,27 +34,16 @@ namespace Magento\Bundle\Model\Product\Attribute\Source\Price;
 class View extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
 {
     /**
-     * Core data
-     *
-     * @var \Magento\Core\Helper\Data
+     * @var OptionFactory
      */
-    protected $_coreData = null;
+    protected $optionFactory;
 
     /**
-     * @var \Magento\Eav\Model\Resource\Entity\Attribute\OptionFactory
+     * @param OptionFactory $optionFactory
      */
-    protected $_entityAttribute;
-
-    /**
-     * @param \Magento\Eav\Model\Resource\Entity\Attribute\OptionFactory $entityAttribute
-     * @param \Magento\Core\Helper\Data $coreData
-     */
-    public function __construct(
-        \Magento\Eav\Model\Resource\Entity\Attribute\OptionFactory $entityAttribute,
-        \Magento\Core\Helper\Data $coreData
-    ) {
-        $this->_coreData = $coreData;
-        $this->_entityAttribute = $entityAttribute;
+    public function __construct(OptionFactory $optionFactory)
+    {
+        $this->optionFactory = $optionFactory;
     }
 
     /**
@@ -61,11 +53,11 @@ class View extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
      */
     public function getAllOptions()
     {
-        if (is_null($this->_options)) {
-            $this->_options = array(
-                array('label' => __('As Low as'), 'value' => 1),
-                array('label' => __('Price Range'), 'value' => 0)
-            );
+        if (null === $this->_options) {
+            $this->_options = [
+                ['label' => __('As Low as'), 'value' => 1],
+                ['label' => __('Price Range'), 'value' => 0],
+            ];
         }
         return $this->_options;
     }
@@ -78,8 +70,7 @@ class View extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
      */
     public function getOptionText($value)
     {
-        $options = $this->getAllOptions();
-        foreach ($options as $option) {
+        foreach ($this->getAllOptions() as $option) {
             if ($option['value'] == $value) {
                 return $option['label'];
             }
@@ -92,16 +83,20 @@ class View extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
      *
      * @return array
      */
-    public function getFlatColums()
+    public function getFlatColumns()
     {
         $attributeCode = $this->getAttribute()->getAttributeCode();
-        $column = array('unsigned' => false, 'default' => null, 'extra' => null);
-
-        $column['type'] = \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER;
-        $column['nullable'] = true;
-        $column['comment'] = 'Bundle Price View ' . $attributeCode . ' column';
 
-        return array($attributeCode => $column);
+        return [
+            $attributeCode => [
+                'unsigned' => false,
+                'default' => null,
+                'extra' => null,
+                'type' => Table::TYPE_INTEGER,
+                'nullable' => true,
+                'comment' => 'Bundle Price View ' . $attributeCode . ' column',
+            ],
+        ];
     }
 
     /**
@@ -112,6 +107,6 @@ class View extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
      */
     public function getFlatUpdateSelect($store)
     {
-        return $this->_entityAttribute->create()->getFlatUpdateSelect($this->getAttribute(), $store, false);
+        return $this->optionFactory->create()->getFlatUpdateSelect($this->getAttribute(), $store, false);
     }
 }
diff --git a/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/AbstractItems.php b/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/AbstractItems.php
index d78d827df2b857653ad757e125073e6af39e06e5..faaa0036e1244120d6e4bf1be0425dc22d5a507c 100644
--- a/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/AbstractItems.php
+++ b/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/AbstractItems.php
@@ -31,7 +31,7 @@ use Magento\Catalog\Model\Product\Type\AbstractType;
 abstract class AbstractItems extends \Magento\Sales\Model\Order\Pdf\Items\AbstractItems
 {
     /**
-     * Getting all available childs for Invoice, Shipmen or Creditmemo item
+     * Getting all available children for Invoice, Shipment or CreditMemo item
      *
      * @param \Magento\Framework\Object $item
      * @return array
@@ -50,12 +50,12 @@ abstract class AbstractItems extends \Magento\Sales\Model\Order\Pdf\Items\Abstra
         }
 
         if ($items) {
-            foreach ($items as $invoiceItem) {
-                $parentItem = $invoiceItem->getOrderItem()->getParentItem();
+            foreach ($items as $value) {
+                $parentItem = $value->getOrderItem()->getParentItem();
                 if ($parentItem) {
-                    $itemsArray[$parentItem->getId()][$invoiceItem->getOrderItemId()] = $invoiceItem;
+                    $itemsArray[$parentItem->getId()][$value->getOrderItemId()] = $value;
                 } else {
-                    $itemsArray[$invoiceItem->getOrderItem()->getId()][$invoiceItem->getOrderItemId()] = $invoiceItem;
+                    $itemsArray[$value->getOrderItem()->getId()][$value->getOrderItemId()] = $value;
                 }
             }
         }
@@ -79,31 +79,18 @@ abstract class AbstractItems extends \Magento\Sales\Model\Order\Pdf\Items\Abstra
             if ($item->getOrderItem()) {
                 $item = $item->getOrderItem();
             }
-
             $parentItem = $item->getParentItem();
             if ($parentItem) {
                 $options = $parentItem->getProductOptions();
                 if ($options) {
-                    if (isset(
-                        $options['shipment_type']
-                    ) && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY
-                    ) {
-                        return true;
-                    } else {
-                        return false;
-                    }
+                    return (isset($options['shipment_type'])
+                        && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY);
                 }
             } else {
                 $options = $item->getProductOptions();
                 if ($options) {
-                    if (isset(
-                        $options['shipment_type']
-                    ) && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY
-                    ) {
-                        return false;
-                    } else {
-                        return true;
-                    }
+                    return !(isset($options['shipment_type'])
+                        && $options['shipment_type'] == AbstractType::SHIPMENT_SEPARATELY);
                 }
             }
         }
@@ -129,40 +116,26 @@ abstract class AbstractItems extends \Magento\Sales\Model\Order\Pdf\Items\Abstra
             if ($item->getOrderItem()) {
                 $item = $item->getOrderItem();
             }
-
             $parentItem = $item->getParentItem();
             if ($parentItem) {
                 $options = $parentItem->getProductOptions();
                 if ($options) {
-                    if (isset(
-                        $options['product_calculations']
-                    ) && $options['product_calculations'] == AbstractType::CALCULATE_CHILD
-                    ) {
-                        return true;
-                    } else {
-                        return false;
-                    }
+                    return (isset($options['product_calculations'])
+                        && $options['product_calculations'] == AbstractType::CALCULATE_CHILD);
                 }
             } else {
                 $options = $item->getProductOptions();
                 if ($options) {
-                    if (isset(
-                        $options['product_calculations']
-                    ) && $options['product_calculations'] == AbstractType::CALCULATE_CHILD
-                    ) {
-                        return false;
-                    } else {
-                        return true;
-                    }
+                    return !(isset($options['product_calculations'])
+                        && $options['product_calculations'] == AbstractType::CALCULATE_CHILD);
                 }
             }
         }
 
         $options = $this->getOrderItem()->getProductOptions();
         if ($options) {
-            if (isset(
-                $options['product_calculations']
-            ) && $options['product_calculations'] == AbstractType::CALCULATE_CHILD
+            if (isset($options['product_calculations'])
+                && $options['product_calculations'] == AbstractType::CALCULATE_CHILD
             ) {
                 return true;
             }
@@ -179,10 +152,8 @@ abstract class AbstractItems extends \Magento\Sales\Model\Order\Pdf\Items\Abstra
     public function getBundleOptions($item = null)
     {
         $options = $this->getOrderItem()->getProductOptions();
-        if ($options) {
-            if (isset($options['bundle_options'])) {
-                return $options['bundle_options'];
-            }
+        if ($options && isset($options['bundle_options'])) {
+            return $options['bundle_options'];
         }
         return array();
     }
diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php
index 00438ad0d5db95a2b06714489c7a0be97d255e7d..5cd71e56ce9ac1f7e84c9a45615054a7c5e6b9c6 100644
--- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php
+++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php
@@ -31,7 +31,7 @@ use Magento\Bundle\Pricing\Price\BundleSelectionFactory;
 use Magento\Framework\Pricing\Adjustment\Calculator as CalculatorBase;
 use Magento\Bundle\Model\Product\Price;
 use Magento\Bundle\Pricing\Price\BundleOptionPrice;
-use Magento\Tax\Model\Calculation as TaxCalculation;
+use Magento\Tax\Service\V1\TaxCalculationServiceInterface;
 use Magento\Store\Model\Store;
 use Magento\Tax\Helper\Data as TaxHelper;
 
@@ -271,7 +271,7 @@ class Calculator implements BundleCalculatorInterface
         $roundingMethod = $this->taxHelper->getCalculationAgorithm($store);
         /** @var \Magento\Framework\Pricing\Amount\AmountInterface $itemAmount */
         foreach ($amountList as $itemAmount) {
-            if ($roundingMethod != TaxCalculation::CALC_TOTAL_BASE) {
+            if ($roundingMethod != TaxCalculationServiceInterface::CALC_TOTAL_BASE) {
                 //We need to round the individual selection first
                 $fullAmount += $store->roundPrice($itemAmount->getValue());
                 foreach ($itemAmount->getAdjustmentAmounts() as $code => $adjustment) {
diff --git a/app/code/Magento/Bundle/Service/V1/Data/Product/Link/Metadata.php b/app/code/Magento/Bundle/Service/V1/Data/Product/Link/Metadata.php
new file mode 100644
index 0000000000000000000000000000000000000000..848048b070522ca74cb48aff27a257f5f7e68b79
--- /dev/null
+++ b/app/code/Magento/Bundle/Service/V1/Data/Product/Link/Metadata.php
@@ -0,0 +1,112 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Service\V1\Data\Product\Link;
+
+use \Magento\Framework\Service\Data\AbstractObject;
+
+/**
+ * @codeCoverageIgnore
+ */
+class Metadata extends AbstractObject
+{
+    const SKU = 'sku';
+
+    const OPTION_ID = 'option_id';
+
+    const QTY = 'qty';
+
+    const POSITION = 'position';
+
+    const DEFINED = 'defined';
+
+    const IS_DEFAULT = 'default';
+
+    const PRICE = 'price';
+
+    const PRICE_TYPE = 'price_type';
+
+    /**
+     * @return string|null
+     */
+    public function getSku()
+    {
+        return $this->_get(self::SKU);
+    }
+
+    /**
+     * @return int|null
+     */
+    public function getOptionId()
+    {
+        return $this->_get(self::OPTION_ID);
+    }
+
+    /**
+     * @return float|null
+     */
+    public function getQty()
+    {
+        return $this->_get(self::QTY);
+    }
+
+    /**
+     * @return int|null
+     */
+    public function getPosition()
+    {
+        return $this->_get(self::POSITION);
+    }
+
+    /**
+     * @return bool
+     */
+    public function isDefined()
+    {
+        return (bool)$this->_get(self::DEFINED);
+    }
+
+    /**
+     * @return bool
+     */
+    public function isDefault()
+    {
+        return (bool)$this->_get(self::IS_DEFAULT);
+    }
+
+    /**
+     * @return float
+     */
+    public function getPrice()
+    {
+        return $this->_get(self::PRICE);
+    }
+
+    /**
+     * @return int
+     */
+    public function getPriceType()
+    {
+        return $this->_get(self::PRICE_TYPE);
+    }
+}
diff --git a/app/code/Magento/Bundle/Service/V1/Data/Product/Link/MetadataBuilder.php b/app/code/Magento/Bundle/Service/V1/Data/Product/Link/MetadataBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..1750b820f7f87c3d9c726f873e702534467d61e4
--- /dev/null
+++ b/app/code/Magento/Bundle/Service/V1/Data/Product/Link/MetadataBuilder.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Service\V1\Data\Product\Link;
+
+use Magento\Framework\Service\Data\AbstractObjectBuilder;
+
+/**
+ * @codeCoverageIgnore
+ */
+class MetadataBuilder extends AbstractObjectBuilder
+{
+    /**
+     * @param string $value
+     * @return $this
+     */
+    public function setSku($value)
+    {
+        return $this->_set(Metadata::SKU, $value);
+    }
+
+    /**
+     * @param float $value
+     * @return $this
+     */
+    public function setQty($value)
+    {
+        return $this->_set(Metadata::QTY, $value);
+    }
+
+    /**
+     * @param int $value
+     * @return $this
+     */
+    public function setPosition($value)
+    {
+        return $this->_set(Metadata::POSITION, $value);
+    }
+
+    /**
+     * @param int $value
+     * @return $this
+     */
+    public function setOptionId($value)
+    {
+        return $this->_set(Metadata::OPTION_ID, $value);
+    }
+
+    /**
+     * @param bool $value
+     * @return $this
+     */
+    public function setDefined($value)
+    {
+        return $this->_set(Metadata::DEFINED, (bool)$value);
+    }
+
+    /**
+     * @param bool $value
+     * @return $this
+     */
+    public function setDefault($value)
+    {
+        return $this->_set(Metadata::IS_DEFAULT, (bool)$value);
+    }
+
+    /**
+     * @param float $value
+     * @return $this
+     */
+    public function setPrice($value)
+    {
+        return $this->_set(Metadata::PRICE, $value);
+    }
+
+    /**
+     * @param int $value
+     * @return $this
+     */
+    public function setPriceType($value)
+    {
+        return $this->_set(Metadata::PRICE_TYPE, $value);
+    }
+}
diff --git a/app/code/Magento/Bundle/Service/V1/Data/Product/Link/MetadataConverter.php b/app/code/Magento/Bundle/Service/V1/Data/Product/Link/MetadataConverter.php
new file mode 100644
index 0000000000000000000000000000000000000000..d62167d6aecfeac692ada141d9a28d23f408b3c5
--- /dev/null
+++ b/app/code/Magento/Bundle/Service/V1/Data/Product/Link/MetadataConverter.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Service\V1\Data\Product\Link;
+
+use Magento\Catalog\Model\Product;
+
+/**
+ * @codeCoverageIgnore
+ */
+class MetadataConverter
+{
+    /**
+     * @var MetadataBuilder
+     */
+    private $builder;
+
+    /**
+     * @param MetadataBuilder $builder
+     */
+    public function __construct(MetadataBuilder $builder)
+    {
+        $this->builder = $builder;
+    }
+
+    /**
+     * @param Product $product
+     * @param Product $bundle
+     * @return Metadata
+     */
+    public function createDataFromModel(Product $product, Product $bundle)
+    {
+        $selectionPriceType = $selectionPrice = null;
+
+        /** @var \Magento\Bundle\Model\Selection $product */
+        if ($bundle->getPriceType()) {
+            $selectionPriceType = $product->getSelectionPriceType();
+            $selectionPrice = $product->getSelectionPriceValue();
+        }
+
+        $this->builder->populateWithArray($product->getData())
+            ->setDefault($product->getIsDefault())
+            ->setQty($product->getSelectionQty())
+            ->setDefined($product->getSelectionCanChangeQty())
+            ->setPrice($selectionPrice)
+            ->setPriceType($selectionPriceType);
+        return $this->builder->create();
+    }
+}
diff --git a/app/code/Magento/Bundle/Service/V1/Product/Link/Data/ProductLink.php b/app/code/Magento/Bundle/Service/V1/Product/Link/Data/ProductLink.php
new file mode 100644
index 0000000000000000000000000000000000000000..9568d0b1e30f3e444171e3247e1dda26327bbd24
--- /dev/null
+++ b/app/code/Magento/Bundle/Service/V1/Product/Link/Data/ProductLink.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Service\V1\Product\Link\Data;
+
+/**
+ * Bundle ProductLink Service Data Object
+ */
+class ProductLink extends \Magento\Framework\Service\Data\Eav\AbstractObject
+{
+    /**
+     * Constants for Data Object keys
+     */
+    const SKU = 'product_sku';
+    const POSITION = 'position';
+    const IS_DEFAULT = 'default';
+    const PRICE_TYPE = 'slection_price_type';
+    const PRICE_VALUE = 'slection_price_value';
+    const QUANTITY = 'selection_qty';
+    const CAN_CHANGE_QUANTITY = 'selection_can_change_qty';
+
+    /**
+     * Get product sku
+     *
+     * @return string
+     */
+    public function getSku()
+    {
+        return $this->_get(self::SKU);
+    }
+
+    /**
+     * Get product position
+     *
+     * @return int
+     */
+    public function getPosition()
+    {
+        return $this->_get(self::POSITION);
+    }
+
+    /**
+     * @return boolean
+     */
+    public function isDefault()
+    {
+        return $this->_get(self::IS_DEFAULT);
+    }
+
+    /**
+     * Get price type
+     *
+     * @return int
+     */
+    public function getPriceType()
+    {
+        return $this->_get(self::PRICE_TYPE);
+    }
+
+    /**
+     * Get price value
+     *
+     * @return float
+     */
+    public function getPriceValue()
+    {
+        return $this->_get(self::PRICE_VALUE);
+    }
+
+    /**
+     * Get quantity
+     *
+     * @return int
+     */
+    public function getQuantity()
+    {
+        return $this->_get(self::QUANTITY);
+    }
+
+    /**
+     * Get whether quantity could be changed
+     *
+     * @return int
+     */
+    public function getCanChangeQuantity()
+    {
+        return $this->_get(self::CAN_CHANGE_QUANTITY);
+    }
+}
diff --git a/app/code/Magento/Bundle/Service/V1/Product/Link/Data/ProductLinkBuilder.php b/app/code/Magento/Bundle/Service/V1/Product/Link/Data/ProductLinkBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..64c5d665f408f04e2f9025b71b8920c0d7412270
--- /dev/null
+++ b/app/code/Magento/Bundle/Service/V1/Product/Link/Data/ProductLinkBuilder.php
@@ -0,0 +1,141 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Service\V1\Product\Link\Data;
+
+use Magento\Framework\Service\Data\Eav\AttributeValueBuilder;
+
+/**
+ * Builder for the ProductLink Service Data Object
+ *
+ * @method ProductLink create()
+ */
+class ProductLinkBuilder extends \Magento\Framework\Service\Data\Eav\AbstractObjectBuilder
+{
+    /**
+     * @var array
+     */
+    protected $customAttributes = [];
+
+    /**
+     * @param \Magento\Framework\Service\Data\ObjectFactory $objectFactory
+     * @param AttributeValueBuilder $valueBuilder
+     * @param array $customAttributesCodes
+     */
+    public function __construct(
+        \Magento\Framework\Service\Data\ObjectFactory $objectFactory,
+        AttributeValueBuilder $valueBuilder,
+        array $customAttributesCodes = array()
+    ) {
+        $this->customAttributes = $customAttributesCodes;
+        parent::__construct($objectFactory, $valueBuilder);
+    }
+
+    /**
+     * Set product sku
+     *
+     * @param string $sku
+     * @return $this
+     */
+    public function setSku($sku)
+    {
+        return $this->_set(ProductLink::SKU, $sku);
+    }
+
+    /**
+     * Set product position
+     *
+     * @param int $position
+     * @return $this
+     */
+    public function setPosition($position)
+    {
+        return $this->_set(ProductLink::POSITION, $position);
+    }
+
+    /**
+     * Get custom attributes codes
+     *
+     * @return string[]
+     */
+    public function getCustomAttributesCodes()
+    {
+        return array_merge(parent::getCustomAttributesCodes(), $this->customAttributes);
+    }
+
+    /**
+     * Set is default
+     *
+     * @param boolean $default
+     * @return $this
+     */
+    public function setDefault($default)
+    {
+        return $this->_set(ProductLink::IS_DEFAULT, $default);
+    }
+
+    /**
+     * Set price type
+     *
+     * @param int $priceType
+     * @return $this
+     */
+    public function setPriceType($priceType)
+    {
+        return $this->_set(ProductLink::PRICE_TYPE, $priceType);
+    }
+
+    /**
+     * Set price value
+     *
+     * @param float $priceValue
+     * @return $this
+     */
+    public function setPriceValue($priceValue)
+    {
+        return $this->_set(ProductLink::PRICE_VALUE, $priceValue);
+    }
+
+    /**
+     * Set quantity
+     *
+     * @param int $priceValue
+     * @return $this
+     */
+    public function setQuantity($quantity)
+    {
+        return $this->_set(ProductLink::QUANTITY, $quantity);
+    }
+
+    /**
+     * Set can change quantity
+     *
+     * @param int $canChangeQuantity
+     * @return $this
+     */
+    public function setCanChangeQuantity($canChangeQuantity)
+    {
+        return $this->_set(ProductLink::CAN_CHANGE_QUANTITY, $canChangeQuantity);
+    }
+}
diff --git a/app/code/Magento/Bundle/Service/V1/Product/Link/ReadService.php b/app/code/Magento/Bundle/Service/V1/Product/Link/ReadService.php
new file mode 100644
index 0000000000000000000000000000000000000000..2cb313a5759bdd3d4f50c3e50e64c85a403668ef
--- /dev/null
+++ b/app/code/Magento/Bundle/Service/V1/Product/Link/ReadService.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Service\V1\Product\Link;
+
+use Magento\Bundle\Model\Option;
+use Magento\Bundle\Service\V1\Data\Product\Link\MetadataConverter;
+use Magento\Catalog\Model\Product;
+use Magento\Catalog\Model\ProductRepository;
+use Magento\Webapi\Exception;
+
+class ReadService implements ReadServiceInterface
+{
+    /**
+     * @var \Magento\Catalog\Model\ProductRepository
+     */
+    private $productRepository;
+
+    /**
+     * @var \Magento\Bundle\Service\V1\Data\Product\Link\MetadataConverter
+     */
+    private $metadataConverter;
+
+    /**
+     * @param ProductRepository $productRepository
+     * @param MetadataConverter $metadataConverter
+     */
+    public function __construct(
+        ProductRepository $productRepository,
+        MetadataConverter $metadataConverter
+    ) {
+
+        $this->productRepository = $productRepository;
+        $this->metadataConverter = $metadataConverter;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getChildren($productId)
+    {
+        $product = $this->productRepository->get($productId);
+
+        if ($product->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) {
+            throw new Exception('Only implemented for bundle product', Exception::HTTP_FORBIDDEN);
+        }
+
+        $childrenList = [];
+        foreach ($this->getOptions($product) as $option) {
+            /** @var \Magento\Catalog\Model\Product $selection */
+            foreach ($option->getSelections() as $selection) {
+                $childrenList[] = $this->metadataConverter->createDataFromModel($selection, $product);
+            }
+        }
+
+        return $childrenList;
+    }
+
+    /**
+     * @param Product $product
+     * @return Option[]
+     */
+    private function getOptions(Product $product)
+    {
+        /** @var \Magento\Bundle\Model\Product\Type $productTypeInstance */
+        $productTypeInstance = $product->getTypeInstance();
+        $productTypeInstance->setStoreFilter(
+            $product->getStoreId(),
+            $product
+        );
+
+        $optionCollection = $productTypeInstance->getOptionsCollection($product);
+
+        $selectionCollection = $productTypeInstance->getSelectionsCollection(
+            $productTypeInstance->getOptionsIds($product),
+            $product
+        );
+
+        $options = $optionCollection->appendSelections($selectionCollection);
+        return $options;
+    }
+}
diff --git a/app/code/Magento/Bundle/Service/V1/Product/Link/ReadServiceInterface.php b/app/code/Magento/Bundle/Service/V1/Product/Link/ReadServiceInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..82d41f220ea88db92cbb483a60549245697089b5
--- /dev/null
+++ b/app/code/Magento/Bundle/Service/V1/Product/Link/ReadServiceInterface.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Service\V1\Product\Link;
+
+interface ReadServiceInterface
+{
+    /**
+     * Get all children for Bundle product
+     *
+     * @param string $productId
+     * @return \Magento\Bundle\Service\V1\Data\Product\Link\Metadata[]
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     * @throws \Magento\Webapi\Exception
+     */
+    public function getChildren($productId);
+}
diff --git a/app/code/Magento/Bundle/Service/V1/Product/Link/WriteService.php b/app/code/Magento/Bundle/Service/V1/Product/Link/WriteService.php
new file mode 100644
index 0000000000000000000000000000000000000000..1218d7fcfa70afd466d9eb365b15a2eafd022538
--- /dev/null
+++ b/app/code/Magento/Bundle/Service/V1/Product/Link/WriteService.php
@@ -0,0 +1,208 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+
+namespace Magento\Bundle\Service\V1\Product\Link;
+
+use Magento\Catalog\Model\ProductRepository;
+use Magento\Framework\Exception\InputException;
+use Magento\Framework\Exception\CouldNotSaveException;
+use Magento\Bundle\Model\Option;
+use Magento\Catalog\Model\Product;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Webapi\Exception;
+
+class WriteService implements WriteServiceInterface
+{
+    /**
+     * @var \Magento\Catalog\Model\ProductRepository
+     */
+    protected $productRepository;
+
+    /**
+     * @var \Magento\Bundle\Model\SelectionFactory $bundleSelection
+     */
+    protected $bundleSelection;
+
+    /**
+     * @var \Magento\Store\Model\StoreManagerInterface
+     */
+    protected $storeManager;
+
+    /**
+     * @var \Magento\Bundle\Model\Resource\BundleFactory
+     */
+    protected $bundleFactory;
+
+    /**
+     * @var \Magento\Bundle\Model\Resource\Option\CollectionFactory
+     */
+    protected $optionCollection;
+
+    /**
+     * @param ProductRepository $productRepository
+     * @param \Magento\Bundle\Model\SelectionFactory $bundleSelection
+     * @param \Magento\Bundle\Model\Resource\BundleFactory $bundleFactory
+     * @param \Magento\Bundle\Model\Resource\Option\CollectionFactory $optionCollection,
+     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
+     */
+    public function __construct(
+        ProductRepository $productRepository,
+        \Magento\Bundle\Model\SelectionFactory $bundleSelection,
+        \Magento\Bundle\Model\Resource\BundleFactory $bundleFactory,
+        \Magento\Bundle\Model\Resource\Option\CollectionFactory $optionCollection,
+        \Magento\Store\Model\StoreManagerInterface $storeManager
+    ) {
+        $this->productRepository = $productRepository;
+        $this->bundleSelection = $bundleSelection;
+        $this->bundleFactory = $bundleFactory;
+        $this->optionCollection = $optionCollection;
+        $this->storeManager = $storeManager;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function addChild($productSku, $optionId, Data\ProductLink $linkedProduct)
+    {
+        /** @var \Magento\Catalog\Model\Product $product */
+        $product = $this->productRepository->get($productSku);
+        if ($product->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) {
+            throw new InputException('Product with specified sku: "%1" is not a bundle product', [$productSku]);
+        }
+
+        $options = $this->optionCollection->create();
+        $options->setProductIdFilter($product->getId())->joinValues($this->storeManager->getStore()->getId());
+        $isNewOption = true;
+        /** @var \Magento\Bundle\Model\Option $option */
+        foreach ($options as $option) {
+            if ($option->getOptionId() == $optionId) {
+                $isNewOption = false;
+                break;
+            }
+        }
+
+        if ($isNewOption) {
+            throw new InputException(
+                'Product with specified sku: "%1" does not contain option: "%2"',
+                [$productSku, $optionId]
+            );
+        }
+
+        /* @var $resource \Magento\Bundle\Model\Resource\Bundle */
+        $resource = $this->bundleFactory->create();
+        $selections = $resource->getSelectionsData($product->getId());
+        /** @var \Magento\Catalog\Model\Product $linkProductModel */
+        $linkProductModel = $this->productRepository->get($linkedProduct->getSku());
+        if ($linkProductModel->isComposite()) {
+            throw new InputException('Bundle product could not contain another composite product');
+        }
+        if ($selections) {
+            foreach ($selections as $selection) {
+                if ($selection['option_id'] == $optionId && $selection['product_id'] == $linkProductModel->getId()) {
+                    throw new CouldNotSaveException(
+                        'Child with specified sku: "%1" already assigned to product: "%2"',
+                        [$linkedProduct->getSku(), $productSku]
+                    );
+                }
+            }
+        }
+
+        $selectionModel = $this->bundleSelection->create();
+        $selectionModel->setOptionId($optionId)
+            ->setPosition($linkedProduct->getPosition())
+            ->setSelectionQty($linkedProduct->getQuantity())
+            ->setSelectionPriceType($linkedProduct->getPriceType())
+            ->setSelectionPriceValue($linkedProduct->getPriceValue())
+            ->setSelectionCanChangeQty($linkedProduct->getCanChangeQuantity())
+            ->setProductId($linkProductModel->getId())
+            ->setParentProductId($product->getId())
+            ->setIsDefault($linkedProduct->isDefault())
+            ->setWebsiteId($this->storeManager->getStore()->getWebsiteId());
+
+        try {
+            $selectionModel->save();
+        } catch (\Exception $e) {
+            throw new CouldNotSaveException('Could not save child: "%1"', [$e->getMessage()], $e);
+        }
+
+        return $selectionModel->getId();
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function removeChild($productSku, $optionId, $childSku)
+    {
+        $product = $this->productRepository->get($productSku);
+
+        if ($product->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) {
+            throw new Exception(
+                sprintf('Product with specified sku: %s is not a bundle product', $productSku),
+                Exception::HTTP_FORBIDDEN
+            );
+        }
+
+        $excludeSelectionIds = array();
+        $usedProductIds = array();
+        $removeSelectionIds = array();
+        foreach ($this->getOptions($product) as $option) {
+            foreach ($option->getSelections() as $selection) {
+                if (($selection->getSku() == $childSku) && ($selection->getOptionId() == $optionId)) {
+                    $removeSelectionIds[] = $selection->getSelectionId();
+                    continue;
+                }
+                $excludeSelectionIds[] = $selection->getSelectionId();
+                $usedProductIds[] = $selection->getProductId();
+            }
+        }
+        if (empty($removeSelectionIds)) {
+            throw new NoSuchEntityException('Requested bundle option product doesn\'t exist');
+        }
+        /* @var $resource \Magento\Bundle\Model\Resource\Bundle */
+        $resource = $this->bundleFactory->create();
+        $resource->dropAllUnneededSelections($product->getId(), $excludeSelectionIds);
+        $resource->saveProductRelations($product->getId(), array_unique($usedProductIds));
+
+        return true;
+    }
+
+    /**
+     * @param Product $product
+     * @return Option[]
+     */
+    private function getOptions(Product $product)
+    {
+        $product->getTypeInstance()->setStoreFilter($product->getStoreId(), $product);
+
+        $optionCollection = $product->getTypeInstance()->getOptionsCollection($product);
+
+        $selectionCollection = $product->getTypeInstance()->getSelectionsCollection(
+            $product->getTypeInstance()->getOptionsIds($product),
+            $product
+        );
+
+        return $optionCollection->appendSelections($selectionCollection);
+    }
+}
diff --git a/app/code/Magento/Bundle/Service/V1/Product/Link/WriteServiceInterface.php b/app/code/Magento/Bundle/Service/V1/Product/Link/WriteServiceInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..44246c350baedb033acdaa5b51a1f5b01935d855
--- /dev/null
+++ b/app/code/Magento/Bundle/Service/V1/Product/Link/WriteServiceInterface.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Service\V1\Product\Link;
+
+interface WriteServiceInterface
+{
+    /**
+     * Add child product to specified Bundle option
+     *
+     * @param string $productSku
+     * @param int $optionId
+     * @param \Magento\Bundle\Service\V1\Product\Link\Data\ProductLink $linkedProduct
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     * @throws \Magento\Framework\Exception\CouldNotSaveException
+     * @throws \Magento\Framework\Exception\InputException
+     * @return int
+     */
+    public function addChild($productSku, $optionId, Data\ProductLink $linkedProduct);
+
+    /**
+     * Remove product from Bundle product option
+     *
+     * @param string $productSku
+     * @param int $optionId
+     * @param string $childSku
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     * @throws \Magento\Webapi\Exception
+     * @return bool
+     */
+    public function removeChild($productSku, $optionId, $childSku);
+}
diff --git a/app/code/Magento/Bundle/etc/di.xml b/app/code/Magento/Bundle/etc/di.xml
index 375f3cd22712cba1601539b44f4595e6510954e6..fd02cc8f4cc9c6f51757c711d460ddbcfb692bd3 100644
--- a/app/code/Magento/Bundle/etc/di.xml
+++ b/app/code/Magento/Bundle/etc/di.xml
@@ -24,6 +24,8 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+    <preference for="Magento\Bundle\Service\V1\Product\Link\ReadServiceInterface" type="Magento\Bundle\Service\V1\Product\Link\ReadService" />
+    <preference for="Magento\Bundle\Service\V1\Product\Link\WriteServiceInterface" type="Magento\Bundle\Service\V1\Product\Link\WriteService" />
     <type name="Magento\Bundle\Model\Source\Option\Type">
         <arguments>
             <argument name="options" xsi:type="array">
diff --git a/app/code/Magento/Bundle/etc/module.xml b/app/code/Magento/Bundle/etc/module.xml
index 8184420b5d516e152364d5f3b92302d776b4ca05..d91076fb651caba4325311453fff37cb8af74c01 100644
--- a/app/code/Magento/Bundle/etc/module.xml
+++ b/app/code/Magento/Bundle/etc/module.xml
@@ -43,6 +43,7 @@
             <module name="Magento_Weee"/>
             <module name="Magento_GiftMessage"/>
             <module name="Magento_Theme"/>
+            <module name="Magento_Webapi"/>
         </depends>
     </module>
 </config>
diff --git a/app/code/Magento/Bundle/etc/webapi.xml b/app/code/Magento/Bundle/etc/webapi.xml
new file mode 100644
index 0000000000000000000000000000000000000000..757c74cee5b1333e78145dedf60219d3239f1f0f
--- /dev/null
+++ b/app/code/Magento/Bundle/etc/webapi.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:noNamespaceSchemaLocation="../../../../../app/code/Magento/Webapi/etc/webapi.xsd">
+    <route url="/V1/bundle-products/:productSku/links/:optionId" method="POST">
+        <service class="Magento\Bundle\Service\V1\Product\Link\WriteServiceInterface" method="addChild"/>
+        <resources>
+            <resource ref="Magento_Catalog::products"/>
+        </resources>
+    </route>
+    <route url="/V1/bundle-products/:productId/children" method="GET">
+        <service class="Magento\Bundle\Service\V1\Product\Link\ReadServiceInterface" method="getChildren"/>
+        <resources>
+            <resource ref="Magento_Catalog::products"/>
+        </resources>
+    </route>
+    <route url="/V1/bundle-products/:productSku/option/:optionId/child/:childSku" method="DELETE">
+        <service class="Magento\Bundle\Service\V1\Product\Link\WriteServiceInterface" method="removeChild"/>
+        <resources>
+            <resource ref="Magento_Catalog::products"/>
+        </resources>
+    </route>
+</routes>
diff --git a/app/code/Magento/Bundle/view/frontend/layout/catalog_product_view_type_bundle.xml b/app/code/Magento/Bundle/view/frontend/layout/catalog_product_view_type_bundle.xml
index 1ac55f7c0a139e32bee81f6ff7cd1502fc1878a5..53f256a2faa9f44f19e11bbe4ea78c528bdb9e60 100644
--- a/app/code/Magento/Bundle/view/frontend/layout/catalog_product_view_type_bundle.xml
+++ b/app/code/Magento/Bundle/view/frontend/layout/catalog_product_view_type_bundle.xml
@@ -45,7 +45,9 @@
                     <argument name="zone" xsi:type="string">item_view</argument>
                 </arguments>
             </block>
-            <block class="Magento\Catalog\Block\Product\View" name="product.info.addtocart.bundle" as="addtocart" template="product/view/addtocart.phtml"/>
+            <block class="Magento\Catalog\Block\Product\View" name="product.info.addtocart.bundle" as="addtocart" template="product/view/addtocart.phtml">
+                <block class="Magento\Catalog\Block\ShortcutButtons\InCatalog" name="addtocart.shortcut.buttons"/>
+            </block>
             <block class="Magento\Catalog\Block\Product\View" name="product.info.addto.bundle" as="addto" template="product/view/addto.phtml"/>
         </block>
     </referenceBlock>
diff --git a/app/code/Magento/Bundle/view/frontend/templates/sales/order/creditmemo/items/renderer.phtml b/app/code/Magento/Bundle/view/frontend/templates/sales/order/creditmemo/items/renderer.phtml
index 4f184dd05239bac1e139fb44fd604bafd0079ea8..c66e9c8e7070c1852be8242538f3dcac810fa2cf 100644
--- a/app/code/Magento/Bundle/view/frontend/templates/sales/order/creditmemo/items/renderer.phtml
+++ b/app/code/Magento/Bundle/view/frontend/templates/sales/order/creditmemo/items/renderer.phtml
@@ -48,156 +48,129 @@
             <?php $_prevOptionId = $attributes['option_id'] ?>
         <?php endif; ?>
     <?php endif; ?>
-<tr<?php echo (++$_index==$_count && !$_showlastRow)?' class="border"':'' ?> id="order-item-row-<?php echo $_item->getId() ?>">
+<tr id="order-item-row-<?php echo $_item->getId() ?>" class="<?php if ($_item->getOrderItem()->getParentItem()): ?>item-options<?php else: ?>item-parent<?php endif; ?>">
     <?php if (!$_item->getOrderItem()->getParentItem()): ?>
-        <td class="col name">
-            <strong class="product name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
+        <td class="col name" data-th="<?php echo $this->escapeHtml(__('Product Name')); ?>">
+            <strong class="product name product-item-name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
         </td>
     <?php else: ?>
-        <td class="col option"><?php echo $this->getValueHtml($_item) ?></td>
+        <td class="col value"><?php echo $this->getValueHtml($_item) ?></td>
     <?php endif; ?>
-    <td class="col sku"><?php echo $this->escapeHtml($_item->getSku()) ?></td>
-    <td class="col price">
+    <td class="col sku" data-th="<?php echo $this->escapeHtml(__('SKU')); ?>"><?php echo $this->escapeHtml($_item->getSku()) ?></td>
+    <td class="col price" data-th="<?php echo $this->escapeHtml(__('Price')); ?>">
         <?php if ($this->canShowPriceInfo($_item)): ?>
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-                <span class="price excl tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart price">
-                    <?php endif; ?>
-                    <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
+            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
+                <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
+                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart tax total"
-                          data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
                 <?php else: ?>
-                <span class="cart price">
-            <?php endif; ?>
+                    <span class="cart price">
+                <?php endif; ?>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
+                    <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
                 <?php else: ?>
-                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
+                    <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
                 <?php endif; ?>
-
-                </span>
+                    </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                    <span class="cart tax info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
+                    <span class="cart tax info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
                         <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                   <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?>
-                                <?php endforeach; ?>
-                            </small>
+                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                            <?php endforeach; ?>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?>
-                                <?php endforeach; ?>
-                            </small>
+                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                            <?php endforeach; ?>
                         <?php endif; ?>
                     </span>
 
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart tax total"
-                              data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                            <?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
+                        <span class="cart-tax-total"
+                              data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                            <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl + $this->getItem()->getWeeeTaxAppliedAmount()); ?></span>
                         </span>
                     <?php endif; ?>
                 <?php endif; ?>
                 </span>
-                <br />
             <?php endif; ?>
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-                <span class="price incl tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart price">
-                    <?php endif; ?>
-                    <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
-                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
+            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
+                <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart tax total"
-                          data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
                 <?php else: ?>
-                <span class="cart price">
-            <?php endif; ?>
+                    <span class="cart price">
+                <?php endif; ?>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
+                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
                 <?php else: ?>
-                    <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
+                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
                 <?php endif; ?>
-                </span>
+                    </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                    <span class="cart tax info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
-                        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?>
-                                <?php endforeach; ?>
-                            </small>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small>
-                            <?php endforeach; ?>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?>
-                                <?php endforeach; ?>
-                            </small>
-                        <?php endif; ?>
+                    <span class="cart-tax-info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
+                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                        <?php endforeach; ?>
+                    <?php endif; ?>
                     </span>
 
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart tax total"
-                              data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                            <?php echo __('Total Incl. Tax'); ?>:<br/> <?php echo $this->getOrder()->formatPrice($_incl + $this->getItem()->getWeeeTaxAppliedAmount()); ?>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?></span>
                         </span>
-                    <?php endif; ?>
                 <?php endif; ?>
-                </span>
+            <?php endif; ?>
+            </span>
             <?php endif; ?>
         <?php else: ?>
             &nbsp;
         <?php endif; ?>
     </td>
-    <td class="col qty">
+    <td class="col qty" data-th="<?php echo $this->escapeHtml(__('Qty')); ?>">
         <?php if ($this->canShowPriceInfo($_item)): ?>
             <?php echo $_item->getQty()*1 ?>
         <?php else: ?>
             &nbsp;
         <?php endif; ?>
     </td>
-    <td class="col subtotal">
+    <td class="col subtotal" data-th="<?php echo $this->escapeHtml(__('Subtotal')); ?>">
         <?php if ($this->canShowPriceInfo($_item)): ?>
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-        <span class="price excl tax">
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart price">
-                <?php endif; ?>
-                <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    </span>
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
+            <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
+                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
+                    <?php echo $this->getOrder()->formatPrice($this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($_item)); ?>
                 <?php endif; ?>
-            <?php endif; ?>
+             </span>
+        <?php else: ?>
+            &nbsp;
+        <?php endif; ?>
+
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
+        <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-            <span class="cart tax total"
+            <span class="cart-tax-total"
                   data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
             <?php else: ?>
                 <span class="cart price">
@@ -211,66 +184,43 @@
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
 
-                    <span class="cart tax info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
+                    <span class="cart-tax-info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
                         <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?>
-                                <?php endforeach; ?>
-                            </small>
+                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                            <?php endforeach; ?>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <small>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?>
-                                </small>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?>
-                                <?php endforeach; ?>
-                            </small>
+                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                            <?php endforeach; ?>
                         <?php endif; ?>
                     </span>
 
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart tax total"
+                        <span class="cart-tax-total"
                               data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                            <?php echo __('Total'); ?>:<br/> <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal() + $this->getItem()->getWeeeTaxAppliedRowAmount() + $this->getItem()->getWeeeTaxRowDisposition()); ?>
+                            <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal() + $this->getItem()->getWeeeTaxAppliedRowAmount() + $this->getItem()->getWeeeTaxRowDisposition()); ?></span>
                         </span>
                     <?php endif; ?>
                 <?php endif; ?>
                 </span>
-                <br />
-            <?php endif; ?>
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-                <span class="price incl tax">
-                    <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                        <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <span class="cart price">
-                        <?php endif; ?>
-                        <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                        <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            </span>
-                        <?php endif; ?>
-                        <?php echo $this->getOrder()->formatPrice($this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($_item)); ?>
-                    <?php endif; ?>
-                 </span>
-            <?php else: ?>
-                &nbsp;
             <?php endif; ?>
         <?php else: ?>
             &nbsp;
         <?php endif; ?>
     </td>
-    <td class="col discount">
+    <td class="col discount" data-th="<?php echo $this->escapeHtml(__('Discount Amount')); ?>">
         <?php if ($this->canShowPriceInfo($_item)): ?>
             <?php echo $this->getOrder()->formatPrice(-$_item->getDiscountAmount()) ?>
         <?php else: ?>
             &nbsp;
         <?php endif; ?>
     </td>
-    <td class="col rowtotal">
+    <td class="col rowtotal" data-th="<?php echo $this->escapeHtml(__('Row Total')); ?>">
         <?php if ($this->canShowPriceInfo($_item)): ?>
             <?php echo $this->getOrder()->formatPrice($_item->getRowTotal()-$_item->getDiscountAmount()+$_item->getTaxAmount()+$_item->getWeeeTaxAppliedRowAmount()) ?>
         <?php else: ?>
diff --git a/app/code/Magento/Bundle/view/frontend/templates/sales/order/invoice/items/renderer.phtml b/app/code/Magento/Bundle/view/frontend/templates/sales/order/invoice/items/renderer.phtml
index fa1d2f378e8df9f2c7026ad5c71f5fe445bec949..2515d5a29c3a269a9eb8fde19f5703c3e9ea8444 100644
--- a/app/code/Magento/Bundle/view/frontend/templates/sales/order/invoice/items/renderer.phtml
+++ b/app/code/Magento/Bundle/view/frontend/templates/sales/order/invoice/items/renderer.phtml
@@ -47,212 +47,122 @@
             <?php $_prevOptionId = $attributes['option_id'] ?>
         <?php endif; ?>
     <?php endif; ?>
-    <tr<?php echo (++$_index==$_count && !$_showlastRow)?' class="border"':'' ?> id="order-item-row-<?php echo $_item->getId() ?>">
+    <tr id="order-item-row-<?php echo $_item->getId() ?>" class="<?php if ($_item->getOrderItem()->getParentItem()): ?>item-options<?php else: ?>item-parent<?php endif; ?>">
     <?php if (!$_item->getOrderItem()->getParentItem()): ?>
-        <td class="col name">
-            <strong class="product name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
+        <td class="col name" data-th="<?php echo $this->escapeHtml(__('Product Name')); ?>">
+            <strong class="product name product-item-name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
         </td>
     <?php else: ?>
         <td class="col value"><?php echo $this->getValueHtml($_item) ?></td>
     <?php endif; ?>
-    <td class="col sku"><?php echo $this->escapeHtml($_item->getSku()) ?></td>
-    <td class="col price">
+    <td class="col sku" data-th="<?php echo $this->escapeHtml(__('SKU')); ?>"><?php echo $this->escapeHtml($_item->getSku()) ?></td>
+    <td class="col price" data-th="<?php echo $this->escapeHtml(__('Price')); ?>">
         <?php if ($this->canShowPriceInfo($_item)): ?>
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-                <span class="price excl tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart price">
-                    <?php endif; ?>
-                    <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
+            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
+                <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
+                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart tax total"
-                          data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
                 <?php else: ?>
-                <span class="cart price">
-            <?php endif; ?>
+                    <span class="cart price">
+                <?php endif; ?>
+
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
+                    <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
                 <?php else: ?>
-                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
+                    <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
                 <?php endif; ?>
-                </span>
-
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                    <span class="cart tax info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"
-                          style="display:none;">
-                        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?>
-                                <?php endforeach; ?>
-                            </small>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small>
-                            <?php endforeach; ?>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?>
-                                <?php endforeach; ?>
-                            </small>
-                        <?php endif; ?>
                     </span>
 
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart tax total"
-                              data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                            <?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
-                        </span>
-                    <?php endif; ?>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+                <span class="cart-tax-info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                    <?php endforeach; ?>
+                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
+                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
                 <?php endif; ?>
+            </span>
+
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                    <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?></span>
                 </span>
-                <br />
             <?php endif; ?>
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-                <span class="price incl tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart price">
-                    <?php endif; ?>
-                    <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
                 <?php endif; ?>
-                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart tax total"
-                          data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                <?php else: ?>
-                <span class="cart price">
+                </span>
             <?php endif; ?>
 
+            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
+                <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                <?php else: ?>
+                    <span class="cart price">
+                <?php endif; ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
+                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
                 <?php else: ?>
-                    <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
+                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
                 <?php endif; ?>
-                </span>
+                    </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                    <span class="cart tax info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
+                    <span class="cart-tax-info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"
+                          style="display: none;">
                         <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?>
-                                <?php endforeach; ?>
-                            </small>
+                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                            <?php endforeach; ?>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?>
-                                <?php endforeach; ?>
-                            </small>
+                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                            <?php endforeach; ?>
                         <?php endif; ?>
                     </span>
 
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart tax total"
-                              data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                            <?php echo __('Total incl. tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
+                        <span class="cart-tax-total"
+                              data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                            <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?></span>
                         </span>
+                        <?php endif; ?>
                     <?php endif; ?>
-                <?php endif; ?>
                 </span>
             <?php endif; ?>
         <?php else: ?>
             &nbsp;
         <?php endif; ?>
     </td>
-    <td class="col qty">
+    <td class="col qty" data-th="<?php echo $this->escapeHtml(__('Qty Invoiced')); ?>">
         <?php if ($this->canShowPriceInfo($_item)): ?>
             <?php echo $_item->getQty()*1 ?>
         <?php else: ?>
             &nbsp;
         <?php endif; ?>
     </td>
-    <td class="col subtotal">
+    <td class="col subtotal" data-th="<?php echo $this->escapeHtml(__('Subtotal')); ?>">
         <?php if ($this->canShowPriceInfo($_item)): ?>
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-        <span class="price excl tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart price">
-                    <?php endif; ?>
-                    <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-            <span class="cart tax total"
-                  data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                <?php else: ?>
-                <span class="cart price">
-                <?php endif; ?>
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
-                <?php else: ?>
-                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
-                <?php endif; ?>
-                </span>
-
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                    <span class="cart tax info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
-                        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?>
-                                <?php endforeach; ?>
-                            </small>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></small>
-                            <?php endforeach; ?>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?>
-                                <?php endforeach; ?>
-                            </small>
-                        <?php endif; ?>
-                    </span>
-
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart tax total"
-                              data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                            <?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
-            </span>
-            <br />
-            <?php endif; ?>
             <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-            <span class="price incl tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart price">
-                    <?php endif; ?>
-                    <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
+                <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
                 <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($this->getItem()); ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <span class="cart tax total"
-                      data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
                 <?php else: ?>
                     <span class="cart price">
                 <?php endif; ?>
@@ -261,38 +171,75 @@
                 <?php else: ?>
                     <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxRowDisposition()) ?>
                 <?php endif; ?>
-                </span>
+                    </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                <span class="cart tax info" id="subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
+                <span class="cart-tax-info" id="subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?>
-                            <?php endforeach; ?>
-                        </small>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                        <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                         <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></small>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
                         <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?>
-                            <?php endforeach; ?>
-                        </small>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                        <?php endforeach; ?>
                     <?php endif; ?>
                 </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart tax total"
+                    <span class="cart-tax-total"
                           data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                        <?php echo __('Total incl. tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?>
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?></span>
                     </span>
                     <?php endif; ?>
                 <?php endif; ?>
             </span>
             <?php endif; ?>
+            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
+                <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                <?php else: ?>
+                    <span class="cart price">
+                <?php endif; ?>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
+                <?php else: ?>
+                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
+                <?php endif; ?>
+                    </span>
+
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+                    <span class="cart-tax-info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                    <?php endforeach; ?>
+                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
+                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                    <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
+                <?php endif; ?>
+                    </span>
+
+                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <span class="cart-tax-total"
+                                  data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?></span>
+                    </span>
+                    <?php endif; ?>
+                <?php endif; ?>
+                </span>
+                <?php endif; ?>
             <?php else: ?>
                 &nbsp;
             <?php endif; ?>
diff --git a/app/code/Magento/Bundle/view/frontend/templates/sales/order/items/renderer.phtml b/app/code/Magento/Bundle/view/frontend/templates/sales/order/items/renderer.phtml
index a81e2dc7e448a1a68235a809167b01d0ca51c096..1581213677eaf570900524d4a02159261bbbf1f8 100644
--- a/app/code/Magento/Bundle/view/frontend/templates/sales/order/items/renderer.phtml
+++ b/app/code/Magento/Bundle/view/frontend/templates/sales/order/items/renderer.phtml
@@ -48,122 +48,95 @@
             <?php $_prevOptionId = $attributes['option_id'] ?>
         <?php endif; ?>
     <?php endif; ?>
-<tr<?php echo (++$_index==$_count && !$_showlastRow)?' class="border"':'' ?> id="order-item-row-<?php echo $_item->getId() ?>">
+<tr id="order-item-row-<?php echo $_item->getId() ?>" class="<?php if ($_item->getParentItem()): ?>item-options<?php else: ?>item-parent<?php endif; ?>">
     <?php if (!$_item->getParentItem()): ?>
-        <td class="col name">
-            <strong class="product name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
+        <td class="col name" data-th="<?php echo $this->escapeHtml(__('Product Name')); ?>">
+            <strong class="product name product-item-name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
         </td>
     <?php else: ?>
         <td class="col value"><?php echo $this->getValueHtml($_item)?></td>
     <?php endif; ?>
-    <td class="col sku"><?php echo $this->prepareSku($_item->getSku()) ?></td>
-    <td class="col price">
+    <td class="col sku" data-th="<?php echo $this->escapeHtml(__('SKU')); ?>"><?php echo $this->prepareSku($_item->getSku()) ?></td>
+    <td class="col price" data-th="<?php echo $this->escapeHtml(__('Price')); ?>">
         <?php if (!$_item->getParentItem()): ?>
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-                <span class="price excl tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart price">
-                    <?php endif; ?>
-                    <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
+            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
+                <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
+                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <span class="cart tax total"
-                      data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
                 <?php else: ?>
-                <span class="cart price">
-            <?php endif; ?>
+                    <span class="cart price">
+                <?php endif; ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
+                    <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
                 <?php else: ?>
-                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
+                    <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
                 <?php endif; ?>
-                </span>
+                    </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                    <span class="cart tax info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"
-                          style="display:none;">
-                        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?>
-                                <?php endforeach; ?>
-                            </small>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small>
-                            <?php endforeach; ?>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?>
-                                <?php endforeach; ?>
-                            </small>
-                        <?php endif; ?>
+                    <span class="cart-tax-info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"
+                          style="display: none;">
+                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                        <?php endforeach; ?>
+                    <?php endif; ?>
                     </span>
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart tax total"
-                              data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                            <?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
+                        <span class="cart-tax-total"
+                              data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                             <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?></span>
                         </span>
                     <?php endif; ?>
                 <?php endif; ?>
                 </span>
-                <br />
             <?php endif; ?>
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-                <span class="price incl tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart price">
-                    <?php endif; ?>
-                    <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    </span>
-                    <?php endif; ?>
-                <?php endif; ?>
-                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
+
+            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
+                <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart tax total"
-                          data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
                 <?php else: ?>
-                <span class="cart price">
-            <?php endif; ?>
+                    <span class="cart price">
+                <?php endif; ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
+                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
                 <?php else: ?>
-                    <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
+                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
                 <?php endif; ?>
-                </span>
-
+                    </span>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                    <span class="cart tax info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"
-                          style="display:none;">
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
+                    <span class="cart-tax-info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"
+                          style="display: none;">
+                        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
                             <?php endforeach; ?>
-                        </small>
-                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small>
-                        <?php endforeach; ?>
-                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
+                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
-                        </small>
-                    <?php endif; ?>
+                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                            <?php endforeach; ?>
+                        <?php endif; ?>
                     </span>
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart tax total"
-                              data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                            <?php echo __('Total incl. tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
+                        <span class="cart-tax-total"
+                              data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                            <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?></span>
                         </span>
                     <?php endif; ?>
                 <?php endif; ?>
@@ -173,140 +146,139 @@
             &nbsp;
         <?php endif; ?>
     </td>
-    <td class="col qty">
+    <td class="col qty" data-th="<?php echo $this->escapeHtml(__('Qty')); ?>">
+        <?php if (
+        ($_item->getParentItem() && $this->isChildCalculated()) ||
+        (!$_item->getParentItem() && !$this->isChildCalculated()) || ($_item->getQtyShipped() > 0 && $_item->getParentItem() && $this->isShipmentSeparately())):?>
+            <ul class="items-qty">
+        <?php endif; ?>
         <?php if (($_item->getParentItem() && $this->isChildCalculated()) ||
             (!$_item->getParentItem() && !$this->isChildCalculated())): ?>
             <?php if ($_item->getQtyOrdered() > 0): ?>
-                <?php echo __('Ordered'); ?>: <strong><?php echo $_item->getQtyOrdered()*1 ?></strong><br />
+                <li class="item">
+                    <span class="title"><?php echo __('Ordered'); ?></span>
+                    <span class="content"><?php echo $_item->getQtyOrdered()*1 ?></span>
+                </li>
+            <?php endif; ?>
+            <?php if ($_item->getQtyShipped() > 0 && !$this->isShipmentSeparately()): ?>
+                <li class="item">
+                    <span class="title"><?php echo __('Shipped'); ?></span>
+                    <span class="content"><?php echo $_item->getQtyShipped()*1 ?></span>
+                </li>
+            <?php endif; ?>
+            <?php if ($_item->getQtyCanceled() > 0): ?>
+                <li class="item">
+                    <span class="title"><?php echo __('Canceled'); ?></span>
+                    <span class="content"><?php echo $_item->getQtyCanceled()*1 ?></span>
+                </li>
+            <?php endif; ?>
+            <?php if ($_item->getQtyRefunded() > 0): ?>
+                <li class="item">
+                    <span class="title"><?php echo __('Refunded'); ?></span>
+                    <span class="content"><?php echo $_item->getQtyRefunded()*1 ?></span>
+                </li>
             <?php endif; ?>
-                <?php if ($_item->getQtyShipped() > 0 && !$this->isShipmentSeparately()): ?>
-                    <?php echo __('Shipped'); ?>: <strong><?php echo $_item->getQtyShipped()*1 ?></strong><br />
-                <?php endif; ?>
-                <?php if ($_item->getQtyCanceled() > 0): ?>
-                    <?php echo __('Canceled'); ?>: <strong><?php echo $_item->getQtyCanceled()*1 ?></strong><br />
-                <?php endif; ?>
-                <?php if ($_item->getQtyRefunded() > 0): ?>
-                    <?php echo __('Refunded'); ?>: <strong><?php echo $_item->getQtyRefunded()*1 ?></strong>
-                <?php endif; ?>
         <?php elseif ($_item->getQtyShipped() > 0 && $_item->getParentItem() && $this->isShipmentSeparately()): ?>
-            <?php echo __('Shipped'); ?>: <strong><?php echo $_item->getQtyShipped()*1 ?></strong>
+            <li class="item">
+                <span class="title"><?php echo __('Shipped'); ?></span>
+                <span class="content"><?php echo $_item->getQtyShipped()*1 ?></span>
+            </li>
         <?php else: ?>
             &nbsp;
         <?php endif; ?>
+        <?php if (
+        ($_item->getParentItem() && $this->isChildCalculated()) ||
+        (!$_item->getParentItem() && !$this->isChildCalculated()) || ($_item->getQtyShipped() > 0 && $_item->getParentItem() && $this->isShipmentSeparately())):?>
+            </ul>
+        <?php endif; ?>
     </td>
-    <td class="col subtotal">
+    <td class="col subtotal" data-th="<?php echo $this->escapeHtml(__('Subtotal')); ?>">
         <?php if (!$_item->getParentItem()): ?>
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-        <span class="price excl tax">
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart price">
-                <?php endif; ?>
-                <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    </span>
-                <?php endif; ?>
-            <?php endif; ?>
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
+            <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
+            <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($this->getItem()); ?>
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-            <span class="cart tax total"
-                  data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
             <?php else: ?>
-            <span class="cart price">
+                <span class="cart price">
             <?php endif; ?>
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
+                <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?>
             <?php else: ?>
-                <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
+                <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxRowDisposition()) ?>
             <?php endif; ?>
-        </span>
+                </span>
 
-        <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-            <span class="cart tax info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"
-                  style="display:none;">
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+                <span class="cart-tax-info"
+                      id="subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"
+                      style="display: none;">
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <small>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?>
-                        <?php endforeach; ?>
-                    </small>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                    <?php endforeach; ?>
                 <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                     <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                        <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></small>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
                     <?php endforeach; ?>
                 <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <small>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?>
-                        <?php endforeach; ?>
-                    </small>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
                 <?php endif; ?>
-            </span>
-
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <span class="cart tax total"
-                      data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                    <?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
                 </span>
-            <?php endif; ?>
-        <?php endif; ?>
-        </span>
-        <br />
-        <?php endif; ?>
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-        <span class="price incl tax">
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart price">
-                <?php endif; ?>
-                <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?></span>
                     </span>
                 <?php endif; ?>
             <?php endif; ?>
-            <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($this->getItem()); ?>
+        </span>
+        <?php endif; ?>
+
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
+            <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-            <span class="cart tax total"
-                  data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
             <?php else: ?>
-            <span class="cart price">
+                <span class="cart price">
             <?php endif; ?>
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
             <?php else: ?>
-                <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxRowDisposition()) ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
             <?php endif; ?>
-            </span>
+                </span>
 
             <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                <span class="cart tax info"
-                      id="subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"
-                      style="display:none;">
+                <span class="cart-tax-info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"
+                      style="display: none;">
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <small>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?>
-                        <?php endforeach; ?>
-                    </small>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                    <?php endforeach; ?>
                 <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                     <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                        <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></small>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
                     <?php endforeach; ?>
                 <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <small>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?>
-                        <?php endforeach; ?>
-                    </small>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
                 <?php endif; ?>
             </span>
 
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart tax total"
-                          data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                    <?php echo __('Total Incl. Tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?>
+                <span class="cart tax total"
+                      data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                    <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?></span>
                 </span>
-                <?php endif; ?>
             <?php endif; ?>
+        <?php endif; ?>
         </span>
         <?php endif; ?>
         <?php else: ?>
diff --git a/app/code/Magento/Bundle/view/frontend/templates/sales/order/shipment/items/renderer.phtml b/app/code/Magento/Bundle/view/frontend/templates/sales/order/shipment/items/renderer.phtml
index d2ee8a251982d5bcfe9a3848ad8b47c7fa4abe41..d47b684a7d80d8891f45eca990aa4bfd502bf86d 100644
--- a/app/code/Magento/Bundle/view/frontend/templates/sales/order/shipment/items/renderer.phtml
+++ b/app/code/Magento/Bundle/view/frontend/templates/sales/order/shipment/items/renderer.phtml
@@ -47,16 +47,16 @@
             <?php $_prevOptionId = $attributes['option_id'] ?>
         <?php endif; ?>
     <?php endif; ?>
-    <tr<?php echo (++$_index==$_count && !$_showlastRow)?' class="border"':'' ?> id="order-item-row-<?php echo $_item->getId() ?>">
+    <tr id="order-item-row-<?php echo $_item->getId() ?>" class="<?php if ($_item->getParentItem()): ?>item-options<?php else: ?>item-parent<?php endif; ?>">
         <?php if (!$_item->getParentItem()): ?>
-            <td class="col name">
-                <strong class="product name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
+            <td class="col name" data-th="<?php echo $this->escapeHtml(__('Product Name')); ?>">
+                <strong class="product name product-item-name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
             </td>
         <?php else: ?>
             <td class="col value"><?php echo $this->getValueHtml($_item) ?></td>
         <?php endif; ?>
-        <td class="col sku"><?php echo $this->escapeHtml($_item->getSku()) ?></td>
-        <td class="col price">
+        <td class="col sku" data-th="<?php echo $this->escapeHtml(__('SKU')); ?>"><?php echo $this->escapeHtml($_item->getSku()) ?></td>
+        <td class="col qty" data-th="<?php echo $this->escapeHtml(__('Qty Shipped')); ?>">
             <?php if (($this->isShipmentSeparately() && $_item->getParentItem()) || (!$this->isShipmentSeparately() && !$_item->getParentItem())): ?>
                 <?php if (isset($shipItems[$_item->getId()])): ?>
                     <?php echo $shipItems[$_item->getId()]->getQty()*1 ?>
diff --git a/app/code/Magento/Captcha/Controller/Refresh/Index.php b/app/code/Magento/Captcha/Controller/Refresh/Index.php
index 7390ed3fe2e4c45543133739ee795bc97a2ae033..aca2ad33b28cf0d66493a37199cbe55e3f04a698 100644
--- a/app/code/Magento/Captcha/Controller/Refresh/Index.php
+++ b/app/code/Magento/Captcha/Controller/Refresh/Index.php
@@ -42,7 +42,7 @@ class Index extends \Magento\Framework\App\Action\Action
      */
     public function __construct(Context $context, \Magento\Captcha\Helper\Data $captchaHelper)
     {
-        $this->captchaHelper;
+        $this->captchaHelper = $captchaHelper;
         parent::__construct($context);
     }
 
diff --git a/app/code/Magento/Catalog/Block/Product/View.php b/app/code/Magento/Catalog/Block/Product/View.php
index 0922334fd41aeec981159d8b5869b622a7747977..fbfd9c6a21048766f298b727396d529e27a01b62 100644
--- a/app/code/Magento/Catalog/Block/Product/View.php
+++ b/app/code/Magento/Catalog/Block/Product/View.php
@@ -46,13 +46,6 @@ class View extends AbstractProduct implements \Magento\Framework\View\Block\Iden
      */
     protected $string;
 
-    /**
-     * Tax calculation
-     *
-     * @var \Magento\Tax\Model\Calculation
-     */
-    protected $_taxCalculation;
-
     /**
      * Product factory
      *
@@ -100,7 +93,6 @@ class View extends AbstractProduct implements \Magento\Framework\View\Block\Iden
      * @param \Magento\Core\Helper\Data $coreData
      * @param \Magento\Framework\Json\EncoderInterface $jsonEncoder
      * @param \Magento\Catalog\Model\ProductFactory $productFactory
-     * @param \Magento\Tax\Model\Calculation $taxCalculation
      * @param \Magento\Framework\Stdlib\String $string
      * @param \Magento\Catalog\Helper\Product $productHelper
      * @param \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig
@@ -114,7 +106,6 @@ class View extends AbstractProduct implements \Magento\Framework\View\Block\Iden
         \Magento\Core\Helper\Data $coreData,
         \Magento\Framework\Json\EncoderInterface $jsonEncoder,
         \Magento\Catalog\Model\ProductFactory $productFactory,
-        \Magento\Tax\Model\Calculation $taxCalculation,
         \Magento\Framework\Stdlib\String $string,
         \Magento\Catalog\Helper\Product $productHelper,
         \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig,
@@ -127,7 +118,6 @@ class View extends AbstractProduct implements \Magento\Framework\View\Block\Iden
         $this->_coreData = $coreData;
         $this->_jsonEncoder = $jsonEncoder;
         $this->_productFactory = $productFactory;
-        $this->_taxCalculation = $taxCalculation;
         $this->productTypeConfig = $productTypeConfig;
         $this->string = $string;
         $this->_localeFormat = $localeFormat;
@@ -258,13 +248,11 @@ class View extends AbstractProduct implements \Magento\Framework\View\Block\Iden
         $product = $this->getProduct();
         $defaultTax = $this->taxCalculationService->getDefaultCalculatedRate(
             $product->getTaxClassId(),
-            $customerId,
-            null
+            $customerId
         );
         $currentTax = $this->taxCalculationService->getCalculatedRate(
             $product->getTaxClassId(),
-            $customerId,
-            null
+            $customerId
         );
 
         $tierPrices = array();
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Validate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Validate.php
index ee694c55342a8781ec3cdfab4ca26ab813dbc4ab..d77522c516bd85bfcb50836541822c6373ac8391 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Validate.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Validate.php
@@ -33,10 +33,10 @@ class Validate extends \Magento\Catalog\Controller\Adminhtml\Product\Action\Attr
      */
     public function execute()
     {
-        $response = new \Magento\Framework\Object();
+        $response = $this->_objectManager->create('Magento\Framework\Object');
         $response->setError(false);
         $attributesData = $this->getRequest()->getParam('attributes', array());
-        $data = new \Magento\Framework\Object();
+        $data = $this->_objectManager->create('Magento\Catalog\Model\Product');
 
         try {
             if ($attributesData) {
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/NewAction.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/NewAction.php
index 45e924542f6f6ec16b811559b880c6b4e6784fc8..089cbd4138478c86f3786c2c2f06e5755fcdb5dc 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/NewAction.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/NewAction.php
@@ -44,7 +44,7 @@ class NewAction extends \Magento\Catalog\Controller\Adminhtml\Product
         Product\Builder $productBuilder,
         Initialization\StockDataFilter $stockFilter
     ) {
-        $this->stockFilter;
+        $this->stockFilter = $stockFilter;
         parent::__construct($context, $productBuilder);
     }
 
diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/Enabled.php b/app/code/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/Enabled.php
index fe205395509e5efe1c2d047e9b2e4eb6d8a26a43..177277dcb6aa5d431af70ef95387c30510b3ade9 100644
--- a/app/code/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/Enabled.php
+++ b/app/code/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/Enabled.php
@@ -29,6 +29,8 @@
  */
 namespace Magento\Catalog\Model\Product\Attribute\Source\Msrp\Type;
 
+use Magento\Framework\DB\Ddl\Table;
+
 class Enabled extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
 {
     /**
@@ -96,17 +98,21 @@ class Enabled extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
      *
      * @return array
      */
-    public function getFlatColums()
+    public function getFlatColumns()
     {
         $attributeCode = $this->getAttribute()->getAttributeCode();
-        $column = array('unsigned' => false, 'default' => null, 'extra' => null);
-
-        $column['type'] = \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT;
-        $column['length'] = 1;
-        $column['nullable'] = true;
-        $column['comment'] = $attributeCode . ' column';
 
-        return array($attributeCode => $column);
+        return [
+            $attributeCode => [
+                'unsigned' => false,
+                'default' => null,
+                'extra' => null,
+                'type' => Table::TYPE_SMALLINT,
+                'length' => 1,
+                'nullable' => true,
+                'comment' => $attributeCode . ' column',
+            ],
+        ];
     }
 
     /**
diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/Price.php b/app/code/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/Price.php
index c9ef383e7504989b67c4f28f6c040e9dda138b71..5c3ebf471b81454e4f7c33583b3ffed6647f653d 100644
--- a/app/code/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/Price.php
+++ b/app/code/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/Price.php
@@ -93,16 +93,20 @@ class Price extends \Magento\Catalog\Model\Product\Attribute\Source\Msrp\Type
      *
      * @return array
      */
-    public function getFlatColums()
+    public function getFlatColumns()
     {
         $attributeType = $this->getAttribute()->getBackendType();
         $attributeCode = $this->getAttribute()->getAttributeCode();
-        $column = array('unsigned' => false, 'default' => null, 'extra' => null);
 
-        $column['type'] = $this->_eavResourceHelper->getDdlTypeByColumnType($attributeType);
-        $column['nullable'] = true;
-
-        return array($attributeCode => $column);
+        return [
+            $attributeCode => [
+                'unsigned' => false,
+                'default' => null,
+                'extra' => null,
+                'type' => $this->_eavResourceHelper->getDdlTypeByColumnType($attributeType),
+                'nullable' => true,
+            ],
+        ];
     }
 
     /**
diff --git a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
index 91aba621f5048ec8e7cfc2f4c4280a9da08f5650..232a6ecd2c996b9c807a283f092561b9e13af912 100644
--- a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
+++ b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
@@ -239,6 +239,8 @@ abstract class AbstractType
      *   group => array(ids)
      * )
      *
+     * @deplacated TODO: refactor to child relation manager
+     *
      * @param int $parentId
      * @param bool $required
      * @return array
diff --git a/app/code/Magento/Catalog/Model/Product/Visibility.php b/app/code/Magento/Catalog/Model/Product/Visibility.php
index 94599886f1daadf9e98a3f0bf88f9a51050a7138..834236eb0461053319d677605b6014673ae1104b 100644
--- a/app/code/Magento/Catalog/Model/Product/Visibility.php
+++ b/app/code/Magento/Catalog/Model/Product/Visibility.php
@@ -30,6 +30,8 @@
  */
 namespace Magento\Catalog\Model\Product;
 
+use Magento\Framework\DB\Ddl\Table;
+
 class Visibility extends \Magento\Framework\Object
 {
     const VISIBILITY_NOT_VISIBLE = 1;
@@ -167,16 +169,20 @@ class Visibility extends \Magento\Framework\Object
      *
      * @return array
      */
-    public function getFlatColums()
+    public function getFlatColumns()
     {
         $attributeCode = $this->getAttribute()->getAttributeCode();
-        $column = array('unsigned' => true, 'default' => null, 'extra' => null);
-
-        $column['type'] = \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT;
-        $column['nullable'] = true;
-        $column['comment'] = 'Catalog Product Visibility ' . $attributeCode . ' column';
 
-        return array($attributeCode => $column);
+        return [
+            $attributeCode => [
+                'unsigned' => true,
+                'default' => null,
+                'extra' => null,
+                'type' => Table::TYPE_SMALLINT,
+                'nullable' => true,
+                'comment' => 'Catalog Product Visibility ' . $attributeCode . ' column',
+            ],
+        ];
     }
 
     /**
diff --git a/app/code/Magento/Catalog/Model/Resource/AbstractResource.php b/app/code/Magento/Catalog/Model/Resource/AbstractResource.php
index 7c76661b2f870983eae9b5cb4b1514a76063d2e4..01ce99b70ceda684f4abd2ca120dfb73cdaeb4bc 100644
--- a/app/code/Magento/Catalog/Model/Resource/AbstractResource.php
+++ b/app/code/Magento/Catalog/Model/Resource/AbstractResource.php
@@ -323,29 +323,31 @@ abstract class AbstractResource extends \Magento\Eav\Model\Entity\AbstractEntity
          * save required attributes in global scope every time if store id different from default
          */
         $storeId = (int) $this->_storeManager->getStore($object->getStoreId())->getId();
-        if ($attribute->getIsRequired() && $this->getDefaultStoreId() != $storeId) {
-            $table = $attribute->getBackend()->getTable();
-
-            $select = $this->_getReadAdapter()->select()
-                ->from($table)
-                ->where('entity_type_id = ?', $attribute->getEntityTypeId())
-                ->where('attribute_id = ?', $attribute->getAttributeId())
-                ->where('store_id = ?', $this->getDefaultStoreId())
-                ->where('entity_id = ?', $object->getEntityId());
-            $row = $this->_getReadAdapter()->fetchOne($select);
-
-            if (!$row) {
-                $data = new \Magento\Framework\Object(
-                    array(
-                        'entity_type_id' => $attribute->getEntityTypeId(),
-                        'attribute_id' => $attribute->getAttributeId(),
-                        'store_id' => $this->getDefaultStoreId(),
-                        'entity_id' => $object->getEntityId(),
-                        'value' => $this->_prepareValueForSave($value, $attribute)
-                    )
-                );
-                $bind = $this->_prepareDataForTable($data, $table);
-                $this->_getWriteAdapter()->insertOnDuplicate($table, $bind, array('value'));
+        if ($this->getDefaultStoreId() != $storeId) {
+            if ($attribute->getIsRequired() || $attribute->getIsRequiredInAdminStore()) {
+                $table = $attribute->getBackend()->getTable();
+
+                $select = $this->_getReadAdapter()->select()
+                    ->from($table)
+                    ->where('entity_type_id = ?', $attribute->getEntityTypeId())
+                    ->where('attribute_id = ?', $attribute->getAttributeId())
+                    ->where('store_id = ?', $this->getDefaultStoreId())
+                    ->where('entity_id = ?', $object->getEntityId());
+                $row = $this->_getReadAdapter()->fetchOne($select);
+
+                if (!$row) {
+                    $data = new \Magento\Framework\Object(
+                        array(
+                            'entity_type_id' => $attribute->getEntityTypeId(),
+                            'attribute_id' => $attribute->getAttributeId(),
+                            'store_id' => $this->getDefaultStoreId(),
+                            'entity_id' => $object->getEntityId(),
+                            'value' => $this->_prepareValueForSave($value, $attribute)
+                        )
+                    );
+                    $bind = $this->_prepareDataForTable($data, $table);
+                    $this->_getWriteAdapter()->insertOnDuplicate($table, $bind, array('value'));
+                }
             }
         }
 
diff --git a/app/code/Magento/Catalog/Service/V1/Data/Converter.php b/app/code/Magento/Catalog/Service/V1/Data/Converter.php
index 69e771ed885a84f15e0c7ca6269e6512af3c29bd..4059993b865b6b822c8fd220cd2a4943b8e69a11 100644
--- a/app/code/Magento/Catalog/Service/V1/Data/Converter.php
+++ b/app/code/Magento/Catalog/Service/V1/Data/Converter.php
@@ -53,7 +53,7 @@ class Converter
      */
     public function createProductDataFromModel(\Magento\Catalog\Model\Product $productModel)
     {
-        $this->_populateBuilderWithAttributes($productModel);
+        $this->populateBuilderWithAttributes($productModel);
         return $this->productBuilder->create();
     }
 
@@ -63,19 +63,19 @@ class Converter
      * @param \Magento\Catalog\Model\Product $productModel
      * @return void
      */
-    protected function _populateBuilderWithAttributes(\Magento\Catalog\Model\Product $productModel)
+    protected function populateBuilderWithAttributes(\Magento\Catalog\Model\Product $productModel)
     {
         $attributes = array();
-        foreach ($this->productBuilder->getCustomAttributesCodes() as $attrCode) {
-            $value = $productModel->getDataUsingMethod($attrCode);
-            $value = $value ? $value : $productModel->getData($attrCode);
+        foreach ($productModel->getAttributes() as $attribute) {
+            $attrCode = $attribute->getAttributeCode();
+            $value = $productModel->getDataUsingMethod($attrCode) ?: $productModel->getData($attrCode);
             if (null !== $value) {
                 if ($attrCode != 'entity_id') {
                     $attributes[$attrCode] = $value;
                 }
             }
         }
-
+        $attributes[ProductDataObject::STORE_ID] = $productModel->getStoreId();
         $this->productBuilder->populateWithArray($attributes);
         return;
     }
diff --git a/app/code/Magento/Catalog/data/catalog_setup/data-upgrade-1.6.0.0.27-1.6.0.0.28.php b/app/code/Magento/Catalog/data/catalog_setup/data-upgrade-1.6.0.0.27-1.6.0.0.28.php
new file mode 100644
index 0000000000000000000000000000000000000000..7258eeaaefe87cf08d5c1881fb2eb1f043ce97c2
--- /dev/null
+++ b/app/code/Magento/Catalog/data/catalog_setup/data-upgrade-1.6.0.0.27-1.6.0.0.28.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/** @var $this \Magento\Catalog\Model\Resource\Setup */
+foreach (['status', 'visibility'] as $attributeCode) {
+    $this->updateAttribute(\Magento\Catalog\Model\Product::ENTITY, $attributeCode, 'is_required_in_admin_store', '1');
+}
diff --git a/app/code/Magento/Catalog/etc/module.xml b/app/code/Magento/Catalog/etc/module.xml
index 991c1e63bfc736bfb28d33d0d73e616faf39594e..f9b6b5c0836fea04b2cd45eae300a4f9e486e52f 100644
--- a/app/code/Magento/Catalog/etc/module.xml
+++ b/app/code/Magento/Catalog/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Catalog" schema_version="1.6.0.0.27" active="true">
+    <module name="Magento_Catalog" schema_version="1.6.0.0.28" active="true">
         <sequence>
             <module name="Magento_Eav"/>
             <module name="Magento_Cms"/>
diff --git a/app/code/Magento/Catalog/sql/catalog_setup/upgrade-1.6.0.0.27-1.6.0.0.28.php b/app/code/Magento/Catalog/sql/catalog_setup/upgrade-1.6.0.0.27-1.6.0.0.28.php
new file mode 100644
index 0000000000000000000000000000000000000000..1ca835e240afae14c33a0313150cbe364fd1f61b
--- /dev/null
+++ b/app/code/Magento/Catalog/sql/catalog_setup/upgrade-1.6.0.0.27-1.6.0.0.28.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/** @var $this \Magento\Catalog\Model\Resource\Setup */
+$this->getConnection()->addColumn(
+    $this->getTable('catalog_eav_attribute'),
+    'is_required_in_admin_store',
+    array(
+        'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
+        'unsigned' => true,
+        'nullable' => false,
+        'default' => '0',
+        'comment' => 'Is Required In Admin Store'
+    )
+);
diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml
index c1b8f640703ed7b9c3c581e48e47e05cdf8a2cdd..8460dbbe28b17ac856e966ca8488f213ec5f56a1 100644
--- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml
+++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml
@@ -77,6 +77,40 @@ jQuery(function($) {
     var $form = $('[data-form=edit-product]');
     $form.data('typeSwitcher', new TypeSwitcher(<?php echo $this->getTypeSwitcherData();?>).bindAll());
 
+    var scriptTagManager = (function($) {
+        var hiddenPrefix = 'hidden',
+            scriptTypeRegExp = /((java|ecma)script)/gi,
+            hiddenScriptType = 'text/' + hiddenPrefix + 'javascript',
+            changeScriptsType = function(source, callback) {
+                var isString = (typeof source === 'string'),
+                    div = document.createElement('div'),
+                    scripts,
+                    scriptsLength;
+                div.innerHTML = isString ? source : $(source).clone().wrap('<p>').parent().html();
+                scripts = div.getElementsByTagName('script');
+                scriptsLength = scripts.length;
+                for (var i = 0; i < scriptsLength; i++) {
+                    scripts[i].type = callback(scripts[i].type);
+                }
+                return isString ? div.innerHTML : $(div.innerHTML);
+            },
+            disableScripts = function(source) {
+                enableScripts(source);
+                return changeScriptsType(source, function(type) {
+                    return type ? type.replace(scriptTypeRegExp, hiddenPrefix + '$1') : hiddenScriptType;
+                });
+            },
+            enableScripts = function(source) {
+                return changeScriptsType(source, function(type) {
+                    return type.replace(hiddenPrefix, '');
+                });
+            };
+        return {
+            'disableScripts' : disableScripts,
+            'enableScripts' : enableScripts
+        }
+    })($);
+
     $('#meta_description').on('change keyup paste', function () {
         var maxLength = $(this).data('maxLength') || 255;
         if ($(this).val().length >= maxLength) {
@@ -225,6 +259,8 @@ jQuery(function($) {
             context: $('body'),
             showLoader: true
         }).done(function(data) {
+            //Hide all js scripts to prevent removing them during jQuery object creation
+            data = scriptTagManager.disableScripts(data);
             var removedElementClass = 'removed';
 
             var $page = $('body');
@@ -283,6 +319,25 @@ jQuery(function($) {
                 });
             });
 
+            //add new fieldsets or reorder
+            $newPage.find('#product_info_tabs .fieldset.user-defined').each(function(index, newFieldset) {
+                var fieldsetContainer, newFieldsetContainer, sourceContainer, destinationContainer;
+                newFieldsetContainer = $(newFieldset).parents('[data-ui-id*=-tab-content-]').first();
+                if ($page.find('[data-ui-id=' + newFieldsetContainer.data('uiId') + ']').length === 0) {
+                    fieldsetContainer = newFieldsetContainer
+                        .clone()
+                        .removeClass(removedElementClass)
+                        .removeClass('ignore-validate');
+                    //Enable hidden js scripts in node. These scripts will be performed after inserting into page
+                    fieldsetContainer = scriptTagManager.enableScripts(fieldsetContainer);
+                } else {
+                    fieldsetContainer = $page.find('[data-ui-id=' + newFieldsetContainer.data('uiId') + ']').first();
+                }
+                sourceContainer = newFieldsetContainer.parents('[data-ui-id*=-tab-content-]').first();
+                destinationContainer = $page.find('[data-ui-id=' + sourceContainer.data('uiId') + ']').first();
+                fieldsetContainer.appendTo(destinationContainer);
+            });
+
             var nameDataMapper = function() {
                 return $(this).data('attributeCode');
             };
diff --git a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml
index 9ca9601a397d1533444c5d00a4f4ea259cd947c1..f089a3adc09dbfd8481744c15e9a64f73822a573 100644
--- a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml
+++ b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml
@@ -164,6 +164,9 @@
     <referenceBlock name="product.info.addtocart">
         <block class="Magento\Catalog\Block\ShortcutButtons\InCatalog" name="addtocart.shortcut.buttons"/>
     </referenceBlock>
+    <referenceBlock name="product.info.addtocart.additional">
+        <block class="Magento\Catalog\Block\ShortcutButtons\InCatalog" name="addtocart.shortcut.buttons.additional"/>
+    </referenceBlock>
     <update handle="MAP_popup"/>
     <update handle="MAP_price_msrp_item"/>
 </layout>
diff --git a/app/code/Magento/Catalog/view/frontend/layout/checkout_cart_item_renderers.xml b/app/code/Magento/Catalog/view/frontend/layout/checkout_cart_item_renderers.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6c53eb77e5a9357b92019e39aeeaeb896fc696a0
--- /dev/null
+++ b/app/code/Magento/Catalog/view/frontend/layout/checkout_cart_item_renderers.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Core/etc/layout_single.xsd">
+    <referenceBlock name="checkout.cart.item.renderers">
+        <block class="Magento\Checkout\Block\Cart\Item\Renderer" as="virtual" template="cart/item/default.phtml"/>
+    </referenceBlock>
+</layout>
diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/compare/list.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/compare/list.phtml
index 23bce71cbcdce364c0dc6b3652b50875840deebd..e3692359697b63390f34e3e3e0deaa05de0d6c05 100644
--- a/app/code/Magento/Catalog/view/frontend/templates/product/compare/list.phtml
+++ b/app/code/Magento/Catalog/view/frontend/templates/product/compare/list.phtml
@@ -29,7 +29,7 @@
         <span><?php echo __('Print This Page') ?></span>
     </a>
     <?php $imageBlock =  $this->getLayout()->createBlock('Magento\Catalog\Block\Product\Image'); ?>
-        <div class="table wrapper comparison">
+        <div class="table-wrapper comparison">
             <table class="data-table data table comparison" id="product-comparison"
                 data-mage-init='{"compareList":{
                     "windowPrintSelector":".action.print",
diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml
index 173982fc6b11b3b4992c90c0fa705ff1bdc6769e..ad8d2c97953cac878890d816254ad968c32812bb 100644
--- a/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml
+++ b/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml
@@ -207,7 +207,7 @@ switch($type = $this->getType()) {
                 <?php if($type == 'related' || $type == 'upsell'): ?>
                     <?php echo ($iterator++==1) ? '<li class="item product product-item" style="display: none;">' : '</li><li class="item product product-item" style="display: none;">' ?>
                 <?php else: ?>
-                    <?php echo ($iterator++==1) ? '<li class="item product product-item">' : '</li><li class="item product">' ?>
+                    <?php echo ($iterator++==1) ? '<li class="item product product-item">' : '</li><li class="item product product-item">' ?>
                 <?php endif; ?>
                 <div class="product-item-info <?php echo $available; ?>">
                     <?php echo '<!-- ' . $image . '-->' ?>
diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/attributes.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/attributes.phtml
index f306387756d7d7d0dc72c44f7d30a1d34bf7fa4f..94886c4777e9f3b4e90c1783a0a383b5497a8ea4 100644
--- a/app/code/Magento/Catalog/view/frontend/templates/product/view/attributes.phtml
+++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/attributes.phtml
@@ -33,7 +33,7 @@
     $_product = $this->getProduct()
 ?>
 <?php if($_additional = $this->getAdditionalData()): ?>
-    <div class="additional attributes table wrapper">
+    <div class="additional attributes table-wrapper">
         <table class="data table additional attributes" id="product-attribute-specs-table">
             <caption class="table caption"><?php echo __('Additional Information') ?></caption>
             <tbody>
diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/details.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/details.phtml
index c554bdf518c75e0114fa1d9cb0610ad18ad744d3..a7f8a836a7be2ebe169b5bf411b835b0a41902ad 100644
--- a/app/code/Magento/Catalog/view/frontend/templates/product/view/details.phtml
+++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/details.phtml
@@ -31,7 +31,7 @@
                     $html = $layout->renderElement($name);
                     if (!trim($html)) continue;
                     $alias = $layout->getElementAlias($name);
-                    $label = $this->escapeHtml($this->getChildData($alias, 'title'));
+                    $label = $this->getChildData($alias, 'title');
                 ?>
                 <div class="data item title" data-role="collapsible"><a class="data switch" data-toggle="switch" href="#<?php echo $alias; ?>"><?php echo $label; ?></a></div>
                 <div class="data item content" id="<?php echo $alias; ?>" data-role="content"><?php echo $html; ?></div>
diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php
index 976c73d7c770fdc918f844dcde246917d4a6f79d..168dbb9978aeb8ddfa030d6774da0bd3c4440cc7 100644
--- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php
@@ -1118,7 +1118,7 @@ class Option extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
      */
     protected function _initProductsSku()
     {
-        if (!$this->_productsSkuToId) {
+        if (!$this->_productsSkuToId || !empty($this->_newOptionsNewData)) {
             $columns = array('entity_id', 'sku');
             foreach ($this->_productModel->getProductEntitiesInfo($columns) as $product) {
                 $this->_productsSkuToId[$product['sku']] = $product['entity_id'];
diff --git a/app/code/Magento/CatalogSearch/Controller/Advanced/Result.php b/app/code/Magento/CatalogSearch/Controller/Advanced/Result.php
index 374328be8e7cc7886385ca1f7ef7014afeec7b3b..804fff22fe29bb90d7b5f51dee72c1eeca4b5fd3 100644
--- a/app/code/Magento/CatalogSearch/Controller/Advanced/Result.php
+++ b/app/code/Magento/CatalogSearch/Controller/Advanced/Result.php
@@ -69,6 +69,8 @@ class Result extends \Magento\Framework\App\Action\Action
     {
         try {
             $this->_catalogSearchAdvanced->addFilters($this->getRequest()->getQuery());
+            $this->_view->loadLayout();
+            $this->_view->renderLayout();
         } catch (\Magento\Framework\Model\Exception $e) {
             $this->messageManager->addError($e->getMessage());
             $defaultUrl = $this->_urlFactory->create()
@@ -76,7 +78,5 @@ class Result extends \Magento\Framework\App\Action\Action
                 ->getUrl('*/*/');
             $this->getResponse()->setRedirect($this->_redirect->error($defaultUrl));
         }
-        $this->_view->loadLayout();
-        $this->_view->renderLayout();
     }
 }
diff --git a/app/code/Magento/CatalogSearch/Controller/Term/Popular.php b/app/code/Magento/CatalogSearch/Controller/Term/Popular.php
index dda99ef9f635877cef3fb7941e00798023f36790..915ef9752fa20e03ab795e3cb344516fb3e48906 100644
--- a/app/code/Magento/CatalogSearch/Controller/Term/Popular.php
+++ b/app/code/Magento/CatalogSearch/Controller/Term/Popular.php
@@ -23,6 +23,7 @@
  */
 namespace Magento\CatalogSearch\Controller\Term;
 
+use Magento\Framework\App\Action\Context;
 use Magento\Framework\App\RequestInterface;
 use Magento\Framework\App\ResponseInterface;
 
@@ -34,11 +35,13 @@ class Popular extends \Magento\Framework\App\Action\Action
     protected $scopeConfig;
 
     /**
+     * @param Context $context
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      */
-    public function __construct(\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig)
+    public function __construct(Context $context, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig)
     {
         $this->scopeConfig = $scopeConfig;
+        parent::__construct($context);
     }
 
     /**
diff --git a/app/code/Magento/CatalogSearch/view/frontend/templates/advanced/result.phtml b/app/code/Magento/CatalogSearch/view/frontend/templates/advanced/result.phtml
index b6bfb179e686f49910c2ea7a6f9ce6376c4b1539..6be10698250f9d1c31deaa4f3dded164e9cb5f72 100644
--- a/app/code/Magento/CatalogSearch/view/frontend/templates/advanced/result.phtml
+++ b/app/code/Magento/CatalogSearch/view/frontend/templates/advanced/result.phtml
@@ -22,6 +22,11 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 ?>
+<?php
+/**
+ * @var $this \Magento\CatalogSearch\Block\Advanced\Result
+ */
+?>
 <?php if($results = $this->getResultCount()): ?>
     <div class="search found">
         <?php if ($results == 1) : ?>
diff --git a/app/code/Magento/CatalogUrlRewrite/Helper/Data.php b/app/code/Magento/CatalogUrlRewrite/Helper/Data.php
new file mode 100644
index 0000000000000000000000000000000000000000..74ab3e84de1f8603a57e39b5e72e300ea00ae7c2
--- /dev/null
+++ b/app/code/Magento/CatalogUrlRewrite/Helper/Data.php
@@ -0,0 +1,277 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CatalogUrlRewrite\Helper;
+
+use Magento\Catalog\Helper\Category as CategoryHelper;
+use Magento\Catalog\Helper\Product as ProductHelper;
+use Magento\Catalog\Model\Category;
+use Magento\Catalog\Model\Product;
+use Magento\Eav\Model\Config;
+use Magento\Framework\App\Resource;
+use Magento\Store\Model\Store;
+use Magento\Store\Model\StoreManagerInterface;
+use Magento\UrlRedirect\Service\V1\Data\Converter;
+use Magento\UrlRedirect\Service\V1\Data\UrlRewrite;
+
+/**
+ * Helper Data
+ */
+class Data
+{
+    /**
+     * Url slash
+     */
+    const URL_SLASH = '/';
+
+    /**
+     * @var \Magento\Eav\Model\Config
+     */
+    protected $eavConfig;
+
+    /**
+     * @var false|\Magento\Framework\DB\Adapter\AdapterInterface
+     */
+    protected $connection;
+
+    /**
+     * @var \Magento\Catalog\Helper\Product
+     */
+    protected $productHelper;
+
+    /**
+     * Store manager
+     *
+     * @var \Magento\Store\Model\StoreManagerInterface
+     */
+    protected $storeManager;
+
+    /**
+     * Catalog category helper
+     *
+     * @var CategoryHelper
+     */
+    protected $categoryHelper;
+
+    /**
+     * @var Converter
+     */
+    protected $converter;
+
+    /**
+     * @param Config $eavConfig
+     * @param Resource $resource
+     * @param \Magento\Catalog\Helper\Product $productHelper
+     * @param StoreManagerInterface $storeManager
+     * @param CategoryHelper $categoryHelper
+     * @param Converter $converter
+     */
+    public function __construct(
+        Config $eavConfig,
+        Resource $resource,
+        ProductHelper $productHelper,
+        StoreManagerInterface $storeManager,
+        CategoryHelper $categoryHelper,
+        Converter $converter
+    ) {
+        $this->eavConfig = $eavConfig;
+        $this->connection = $resource->getConnection(Resource::DEFAULT_READ_RESOURCE);
+        $this->productHelper = $productHelper;
+        $this->storeManager = $storeManager;
+        $this->categoryHelper = $categoryHelper;
+        $this->converter = $converter;
+    }
+
+    /**
+     * If product saved on default store view, then need to check specific url_key for other stores
+     *
+     * @param int $storeId
+     * @param int $productId
+     * @return bool
+     */
+    public function isNeedCreateUrlRewrite($storeId, $productId)
+    {
+        $attribute = $this->eavConfig->getAttribute(Product::ENTITY, 'url_key');
+        $select = $this->connection->select()
+            ->from($attribute->getBackendTable(), 'store_id')
+            ->where('attribute_id = ?', $attribute->getId())
+            ->where('entity_id = ?', $productId);
+
+        return !in_array($storeId, $this->connection->fetchCol($select));
+    }
+
+    /**
+     * Whether the store is default
+     *
+     * @param int|null $storeId
+     * @return bool
+     */
+    public function isDefaultStore($storeId)
+    {
+        return null === $storeId || $storeId == Store::DEFAULT_STORE_ID;
+    }
+
+    /**
+     * Get canonical product url path
+     *
+     * @param Product $product
+     * @return string
+     */
+    public function getProductCanonicalUrlPath(Product $product)
+    {
+        return 'catalog/product/view/id/' . $product->getId();
+    }
+
+    /**
+     * Get canonical product url path with category
+     *
+     * @param Product $product
+     * @param Category $category
+     * @return string
+     */
+    public function getProductCanonicalUrlPathWithCategory(Product $product, Category $category)
+    {
+        return $this->getProductCanonicalUrlPath($product) . '/category/' . $category->getId();
+    }
+
+    /**
+     * Get product url key path
+     *
+     * @param Product $product
+     * @param int $storeId
+     * @return string
+     */
+    public function getProductUrlKeyPath(Product $product, $storeId)
+    {
+        return $product->getUrlModel()->getUrlPath($product) . $this->productHelper->getProductUrlSuffix($storeId);
+    }
+
+    /**
+     * Get product url key path with category
+     *
+     * @param Product $product
+     * @param Category $category
+     * @param int $storeId
+     * @return string
+     */
+    public function getProductUrlKeyPathWithCategory(Product $product, Category $category, $storeId)
+    {
+        return $product->getUrlModel()->getUrlPath($product, $category)
+            . $this->productHelper->getProductUrlSuffix($storeId);
+    }
+
+    /**
+     * Get canonical category url
+     *
+     * @param Category $category
+     * @return string
+     */
+    public function getCategoryCanonicalUrlPath(Category $category)
+    {
+        return 'catalog/category/view/id/' . $category->getId();
+    }
+
+    /**
+     * Get category url path
+     *
+     * @param Category $category
+     * @return string
+     */
+    public function getCategoryUrlKeyPath(Category $category)
+    {
+        return $category->getUrlPath();
+    }
+
+    /**
+     * Check is root category
+     *
+     * @param Category $category
+     * @return string
+     */
+    public function isRootCategory(Category $category)
+    {
+        $store = $this->storeManager->getStore($category->getStoreId());
+
+        return $category->getId() == $store->getRootCategoryId();
+    }
+
+    /**
+     * Generate category url key path
+     *
+     * @param \Magento\Catalog\Model\Category $category
+     * @return string
+     */
+    public function generateCategoryUrlKeyPath($category)
+    {
+        $parentPath = $this->categoryHelper->getCategoryUrlPath('', true, $category->getStoreId());
+
+        $urlKey = $category->getUrlKey() == ''
+            ? $category->formatUrlKey($category->getName()) : $category->formatUrlKey($category->getUrlKey());
+
+        return $parentPath . $urlKey;
+    }
+
+    /**
+     * Generate product url key path
+     *
+     * @param \Magento\Catalog\Model\Product $product
+     * @return string
+     */
+    public function generateProductUrlKeyPath($product)
+    {
+        $urlKey = $product->getUrlKey() == ''
+            ? $product->formatUrlKey($product->getName())
+            : $product->formatUrlKey($product->getUrlKey());
+
+        return $urlKey;
+    }
+
+    /**
+     * Create url rewrite object
+     *
+     * @param string $entityType
+     * @param int $entityId
+     * @param int $storeId
+     * @param string $requestPath
+     * @param string $targetPath
+     * @param string|null $redirectType Null or one of OptionProvider const
+     * @return UrlRewrite
+     */
+    public function createUrlRewrite(
+        $entityType,
+        $entityId,
+        $storeId,
+        $requestPath,
+        $targetPath,
+        $redirectType = null
+    ) {
+        return $this->converter->convertArrayToObject([
+            UrlRewrite::ENTITY_TYPE => $entityType,
+            UrlRewrite::ENTITY_ID => $entityId,
+            UrlRewrite::STORE_ID => $storeId,
+            UrlRewrite::REQUEST_PATH => $requestPath,
+            UrlRewrite::TARGET_PATH => $targetPath,
+            UrlRewrite::REDIRECT_TYPE => $redirectType,
+        ]);
+    }
+}
diff --git a/app/code/Magento/CatalogUrlRewrite/Model/Category/Observer.php b/app/code/Magento/CatalogUrlRewrite/Model/Category/Observer.php
new file mode 100644
index 0000000000000000000000000000000000000000..c2387d36e4bb60211f8d7abb97076d9cb720da64
--- /dev/null
+++ b/app/code/Magento/CatalogUrlRewrite/Model/Category/Observer.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CatalogUrlRewrite\Model\Category;
+
+use Magento\CatalogUrlRewrite\Helper\Data as CatalogUrlRewriteHelper;
+use Magento\CatalogUrlRewrite\Service\V1\CategoryUrlGeneratorInterface;
+use Magento\CatalogUrlRewrite\Service\V1\ProductUrlGeneratorInterface;
+use Magento\Framework\Event\Observer as EventObserver;
+use Magento\UrlRedirect\Service\V1\UrlSaveInterface;
+
+class Observer
+{
+    /**
+     * @var CategoryUrlGeneratorInterface
+     */
+    protected $categoryUrlGenerator;
+
+    /**
+     * @var CategoryUrlGeneratorInterface
+     */
+    protected $productUrlGenerator;
+
+    /**
+     * @var UrlSaveInterface
+     */
+    protected $urlSave;
+
+    /**
+     * @var CatalogUrlRewriteHelper
+     */
+    protected $catalogUrlRewriteHelper;
+
+    /**
+     * @param CategoryUrlGeneratorInterface $categoryUrlGenerator
+     * @param ProductUrlGeneratorInterface $productUrlGenerator
+     * @param UrlSaveInterface $urlSave
+     * @param CatalogUrlRewriteHelper $catalogUrlRewriteHelper
+     */
+    public function __construct(
+        CategoryUrlGeneratorInterface $categoryUrlGenerator,
+        ProductUrlGeneratorInterface $productUrlGenerator,
+        UrlSaveInterface $urlSave,
+        CatalogUrlRewriteHelper $catalogUrlRewriteHelper
+    ) {
+        $this->categoryUrlGenerator = $categoryUrlGenerator;
+        $this->productUrlGenerator = $productUrlGenerator;
+        $this->urlSave = $urlSave;
+        $this->catalogUrlRewriteHelper = $catalogUrlRewriteHelper;
+    }
+
+    /**
+     * Generate urls for UrlRewrite and save it in storage
+     *
+     * @param \Magento\Framework\Event\Observer $observer
+     * @return void
+     */
+    public function processUrlRewriteSaving(EventObserver $observer)
+    {
+        /** @var \Magento\Catalog\Model\Category $category */
+        $category = $observer->getEvent()->getCategory();
+
+        if (!$this->catalogUrlRewriteHelper->isRootCategory($category)
+            && (!$category->getData('url_key') || $category->getOrigData('url_key') != $category->getData('url_key'))
+        ) {
+            $this->urlSave->save($this->categoryUrlGenerator->generate($category));
+
+            $products = $category->getProductCollection()
+                ->addAttributeToSelect('url_key')
+                ->addAttributeToSelect('url_path');
+
+            foreach ($products as $product) {
+                $product->setData('save_rewrites_history', $category->getData('save_rewrites_history'));
+
+                $this->urlSave->save($this->productUrlGenerator->generateWithChangedCategories(
+                    $product,
+                    [$category->getId() => $category]
+                ));
+            }
+        }
+    }
+}
diff --git a/app/code/Magento/CatalogUrlRewrite/Model/Product/Observer.php b/app/code/Magento/CatalogUrlRewrite/Model/Product/Observer.php
new file mode 100644
index 0000000000000000000000000000000000000000..9dfbb358ce570d98b6fc0c536b82c63278db0d58
--- /dev/null
+++ b/app/code/Magento/CatalogUrlRewrite/Model/Product/Observer.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CatalogUrlRewrite\Model\Product;
+
+use Magento\CatalogUrlRewrite\Helper\Data as CatalogUrlRewriteHelper;
+use Magento\CatalogUrlRewrite\Service\V1\ProductUrlGeneratorInterface;
+use Magento\Framework\Event\Observer as EventObserver;
+use Magento\UrlRedirect\Service\V1\UrlSaveInterface;
+
+class Observer
+{
+    /**
+     * @var ProductUrlGeneratorInterface
+     */
+    protected $productUrlGenerator;
+
+    /**
+     * @var UrlSaveInterface
+     */
+    protected $urlSave;
+
+    /**
+     * @var CatalogUrlRewriteHelper
+     */
+    protected $catalogUrlRewriteHelper;
+
+    /**
+     * @param ProductUrlGeneratorInterface $productUrlGenerator
+     * @param UrlSaveInterface $urlSave
+     * @param CatalogUrlRewriteHelper $catalogUrlRewriteHelper
+     */
+    public function __construct(
+        ProductUrlGeneratorInterface $productUrlGenerator,
+        UrlSaveInterface $urlSave,
+        CatalogUrlRewriteHelper $catalogUrlRewriteHelper
+    ) {
+        $this->productUrlGenerator = $productUrlGenerator;
+        $this->urlSave = $urlSave;
+        $this->catalogUrlRewriteHelper = $catalogUrlRewriteHelper;
+    }
+
+    /**
+     * Generate urls for UrlRewrite and save it in storage
+     *
+     * @param \Magento\Framework\Event\Observer $observer
+     * @return void
+     */
+    public function processUrlRewriteSaving(EventObserver $observer)
+    {
+        /** @var \Magento\Catalog\Model\Product $product */
+        $product = $observer->getEvent()->getProduct();
+
+        if (!$product->getUrlPath() || $product->getOrigData('url_key') != $product->getData('url_key')) {
+            $product->setUrlPath($this->catalogUrlRewriteHelper->generateProductUrlKeyPath($product));
+        }
+
+        if (!$product->getData('url_key') || $product->getOrigData('url_key') != $product->getData('url_key')) {
+            $this->urlSave->save($this->productUrlGenerator->generate($product));
+        }
+    }
+}
diff --git a/app/code/Magento/CatalogUrlRewrite/Service/V1/AbstractUrlGenerator.php b/app/code/Magento/CatalogUrlRewrite/Service/V1/AbstractUrlGenerator.php
new file mode 100644
index 0000000000000000000000000000000000000000..3a6925dee2eab674d280e83ce30d3a43b3bd706f
--- /dev/null
+++ b/app/code/Magento/CatalogUrlRewrite/Service/V1/AbstractUrlGenerator.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CatalogUrlRewrite\Service\V1;
+
+use Magento\Catalog\Model\ProductFactory;
+use Magento\CatalogUrlRewrite\Helper\Data as CatalogUrlRewriteHelper;
+use Magento\Store\Model\StoreManagerInterface;
+use Magento\UrlRedirect\Model\OptionProvider;
+use Magento\UrlRedirect\Service\V1\Data\Converter;
+use Magento\UrlRedirect\Service\V1\Data\FilterFactory;
+use Magento\UrlRedirect\Service\V1\Data\UrlRewrite;
+use Magento\UrlRedirect\Service\V1\UrlMatcherInterface;
+
+/**
+ * Product Generator
+ */
+abstract class AbstractUrlGenerator
+{
+}
diff --git a/app/code/Magento/CatalogUrlRewrite/Service/V1/CategoryUrlGenerator.php b/app/code/Magento/CatalogUrlRewrite/Service/V1/CategoryUrlGenerator.php
new file mode 100644
index 0000000000000000000000000000000000000000..cbb770f46f0af4abd836579aa61c265b0209ff13
--- /dev/null
+++ b/app/code/Magento/CatalogUrlRewrite/Service/V1/CategoryUrlGenerator.php
@@ -0,0 +1,213 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CatalogUrlRewrite\Service\V1;
+
+use Magento\CatalogUrlRewrite\Helper\Data as CatalogUrlRewriteHelper;
+use Magento\Store\Model\StoreManagerInterface;
+use Magento\UrlRedirect\Model\OptionProvider;
+use Magento\UrlRedirect\Service\V1\Data\FilterFactory;
+use Magento\UrlRedirect\Service\V1\UrlMatcherInterface;
+use Magento\UrlRedirect\Service\V1\Data\UrlRewrite;
+
+/**
+ * Product Generator
+ */
+class CategoryUrlGenerator implements CategoryUrlGeneratorInterface
+{
+    /**
+     * Entity type
+     */
+    const ENTITY_TYPE_CATEGORY = 'category';
+
+    /**
+     * @var FilterFactory
+     */
+    protected $filterFactory;
+
+    /**
+     * Store manager
+     *
+     * @var StoreManagerInterface
+     */
+    protected $storeManager;
+
+    /**
+     * @var UrlMatcherInterface
+     */
+    protected $urlMatcher;
+
+    /**
+     * @var CatalogUrlRewriteHelper
+     */
+    protected $catalogUrlRewriteHelper;
+
+    /**
+     * @var \Magento\Catalog\Model\Category
+     */
+    protected $category;
+
+    /**
+     * @var null|\Magento\Catalog\Model\Resource\Category\Collection
+     */
+    protected $categories;
+
+    /**
+     * @param FilterFactory $filterFactory
+     * @param StoreManagerInterface $storeManager
+     * @param UrlMatcherInterface $urlMatcher
+     * @param CatalogUrlRewriteHelper $catalogUrlRewriteHelper
+     */
+    public function __construct(
+        FilterFactory $filterFactory,
+        StoreManagerInterface $storeManager,
+        UrlMatcherInterface $urlMatcher,
+        CatalogUrlRewriteHelper $catalogUrlRewriteHelper
+    ) {
+        $this->filterFactory = $filterFactory;
+        $this->storeManager = $storeManager;
+        $this->urlMatcher = $urlMatcher;
+        $this->catalogUrlRewriteHelper = $catalogUrlRewriteHelper;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function generate($category)
+    {
+        $this->category = $category;
+        $storeId = $this->category->getStoreId();
+
+        $urls = $this->catalogUrlRewriteHelper->isDefaultStore($storeId)
+            ? $this->generateForDefaultStore() : $this->generateForStore($storeId);
+
+        $this->category = null;
+        return $urls;
+    }
+
+    /**
+     * Generate list of urls for default store
+     *
+     * @return UrlRewrite[]
+     */
+    protected function generateForDefaultStore()
+    {
+        $urls = [];
+        foreach ($this->storeManager->getStores() as $store) {
+            if ($this->catalogUrlRewriteHelper->isNeedCreateUrlRewrite(
+                $store->getStoreId(),
+                $this->category->getId()
+            )) {
+                $urls = array_merge($urls, $this->generateForStore($store->getStoreId()));
+            }
+        }
+        return $urls;
+    }
+
+    /**
+     * Generate list of urls per store
+     *
+     * @param int $storeId
+     * @return UrlRewrite[]
+     */
+    protected function generateForStore($storeId)
+    {
+        $urls[] = $this->createUrlRewrite(
+            $storeId,
+            $this->catalogUrlRewriteHelper->getCategoryUrlKeyPath($this->category),
+            $this->catalogUrlRewriteHelper->getCategoryCanonicalUrlPath($this->category)
+        );
+
+        return array_merge($urls, $this->generateRewritesBasedOnCurrentRewrites($storeId));
+    }
+
+    /**
+     * Generate permanent rewrites based on current rewrites
+     *
+     * @param int $storeId
+     * @return array
+     */
+    protected function generateRewritesBasedOnCurrentRewrites($storeId)
+    {
+        $urls = [];
+        foreach ($this->urlMatcher->findAllByFilter($this->createCurrentUrlRewritesFilter($storeId)) as $url) {
+            $targetPath = null;
+            if ($url->getRedirectType()) {
+                $targetPath = str_replace(
+                    $this->category->getOrigData('url_key'),
+                    $this->category->getData('url_key'),
+                    $url->getTargetPath()
+                );
+                $redirectType = $url->getRedirectType();
+            } elseif ($this->category->getData('save_rewrites_history')) {
+                $targetPath = str_replace(
+                    $this->category->getOrigData('url_key'),
+                    $this->category->getData('url_key'),
+                    $url->getRequestPath()
+                );
+                $redirectType = OptionProvider::PERMANENT;
+            }
+
+            if ($targetPath && $url->getRequestPath() != $targetPath) {
+                $urls[] = $this->createUrlRewrite($storeId, $url->getRequestPath(), $targetPath, $redirectType);
+            }
+        }
+        return $urls;
+    }
+
+    /**
+     * @param int $storeId
+     * @return \Magento\UrlRedirect\Service\V1\Data\Filter
+     */
+    protected function createCurrentUrlRewritesFilter($storeId)
+    {
+        /** @var \Magento\UrlRedirect\Service\V1\Data\Filter $filter */
+        $filter = $this->filterFactory->create();
+
+        $filter->setStoreId($storeId);
+        $filter->setEntityId($this->category->getId());
+        $filter->setEntityType(self::ENTITY_TYPE_CATEGORY);
+        return $filter;
+    }
+
+    /**
+     * Create url rewrite object
+     *
+     * @param int $storeId
+     * @param string $requestPath
+     * @param string $targetPath
+     * @param string|null $redirectType Null or one of OptionProvider const
+     * @return UrlRewrite
+     */
+    protected function createUrlRewrite($storeId, $requestPath, $targetPath, $redirectType = null)
+    {
+        return $this->catalogUrlRewriteHelper->createUrlRewrite(
+            self::ENTITY_TYPE_CATEGORY,
+            $this->category->getId(),
+            $storeId,
+            $requestPath,
+            $targetPath,
+            $redirectType
+        );
+    }
+}
diff --git a/app/code/Magento/CatalogUrlRewrite/Service/V1/CategoryUrlGeneratorInterface.php b/app/code/Magento/CatalogUrlRewrite/Service/V1/CategoryUrlGeneratorInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..c9288d01e6e74f34c264f1028b44595530153fc8
--- /dev/null
+++ b/app/code/Magento/CatalogUrlRewrite/Service/V1/CategoryUrlGeneratorInterface.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CatalogUrlRewrite\Service\V1;
+
+/**
+ * Product Generator
+ */
+interface CategoryUrlGeneratorInterface
+{
+    /**
+     * Generate list of urls
+     *
+     * @param \Magento\Catalog\Model\Category $category
+     * @return \Magento\UrlRedirect\Service\V1\Data\UrlRewrite[]
+     */
+    public function generate($category);
+}
diff --git a/app/code/Magento/CatalogUrlRewrite/Service/V1/ProductUrlGenerator.php b/app/code/Magento/CatalogUrlRewrite/Service/V1/ProductUrlGenerator.php
new file mode 100644
index 0000000000000000000000000000000000000000..a6991bc1c0f24b2d1504526b05f49f0c7bc3b072
--- /dev/null
+++ b/app/code/Magento/CatalogUrlRewrite/Service/V1/ProductUrlGenerator.php
@@ -0,0 +1,254 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CatalogUrlRewrite\Service\V1;
+
+use Magento\CatalogUrlRewrite\Helper\Data as CatalogUrlRewriteHelper;
+use Magento\Store\Model\StoreManagerInterface;
+use Magento\UrlRedirect\Model\OptionProvider;
+use Magento\UrlRedirect\Service\V1\Data\FilterFactory;
+use Magento\UrlRedirect\Service\V1\UrlMatcherInterface;
+
+/**
+ * Product Generator
+ */
+class ProductUrlGenerator implements ProductUrlGeneratorInterface
+{
+    /**
+     * Entity type
+     */
+    const ENTITY_TYPE_PRODUCT = 'product';
+
+    /**
+     * @var FilterFactory
+     */
+    protected $filterFactory;
+
+    /**
+     * Store manager
+     *
+     * @var StoreManagerInterface
+     */
+    protected $storeManager;
+
+    /**
+     * @var UrlMatcherInterface
+     */
+    protected $urlMatcher;
+
+    /**
+     * @var CatalogUrlRewriteHelper
+     */
+    protected $catalogUrlRewriteHelper;
+
+    /**
+     * @var \Magento\Catalog\Model\Product
+     */
+    protected $product;
+
+    /**
+     * @var null|\Magento\Catalog\Model\Resource\Category\Collection
+     */
+    protected $categories;
+
+    /**
+     * @var \Magento\Catalog\Model\Category[]
+     */
+    protected $changedCategories;
+
+    /**
+     * @param FilterFactory $filterFactory
+     * @param StoreManagerInterface $storeManager
+     * @param UrlMatcherInterface $urlMatcher
+     * @param CatalogUrlRewriteHelper $catalogUrlRewriteHelper
+     */
+    public function __construct(
+        FilterFactory $filterFactory,
+        StoreManagerInterface $storeManager,
+        UrlMatcherInterface $urlMatcher,
+        CatalogUrlRewriteHelper $catalogUrlRewriteHelper
+    ) {
+        $this->filterFactory = $filterFactory;
+        $this->storeManager = $storeManager;
+        $this->urlMatcher = $urlMatcher;
+        $this->catalogUrlRewriteHelper = $catalogUrlRewriteHelper;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function generate($product)
+    {
+        $this->product = $product;
+        $storeId = $this->product->getStoreId();
+
+        $urls = $this->catalogUrlRewriteHelper->isDefaultStore($storeId)
+            ? $this->generateForDefaultStore() : $this->generateForStore($storeId);
+
+        $this->product = null;
+        $this->categories = null;
+        return $urls;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function generateWithChangedCategories($product, $changedCategories)
+    {
+        $this->changedCategories = $changedCategories;
+
+        return $this->generate($product);
+    }
+
+    /**
+     * Generate list of urls for default store
+     *
+     * @return \Magento\UrlRedirect\Service\V1\Data\UrlRewrite[]
+     */
+    protected function generateForDefaultStore()
+    {
+        $urls = [];
+        foreach ($this->storeManager->getStores() as $store) {
+            if ($this->catalogUrlRewriteHelper->isNeedCreateUrlRewrite($store->getStoreId(), $this->product->getId())) {
+                $urls = array_merge($urls, $this->generateForStore($store->getStoreId()));
+            }
+        }
+        return $urls;
+    }
+
+    /**
+     * Generate list of urls per store
+     *
+     * @param int $storeId
+     * @return \Magento\UrlRedirect\Service\V1\Data\UrlRewrite[]
+     */
+    protected function generateForStore($storeId)
+    {
+        $urls[] = $this->createUrlRewrite(
+            $storeId,
+            $this->catalogUrlRewriteHelper->getProductUrlKeyPath($this->product, $storeId),
+            $this->catalogUrlRewriteHelper->getProductCanonicalUrlPath($this->product)
+        );
+
+        foreach ($this->getCategories() as $category) {
+            if (isset($this->changedCategories[$category->getId()])) {
+                $category = $this->changedCategories[$category->getId()];
+            }
+
+            if ($this->catalogUrlRewriteHelper->isRootCategory($category)) {
+                continue;
+            }
+            $urls[] = $this->createUrlRewrite(
+                $storeId,
+                $this->catalogUrlRewriteHelper->getProductUrlKeyPathWithCategory($this->product, $category, $storeId),
+                $this->catalogUrlRewriteHelper->getProductCanonicalUrlPathWithCategory($this->product, $category)
+            );
+        }
+        return array_merge($urls, $this->generateRewritesBasedOnCurrentRewrites($storeId));
+    }
+
+    /**
+     * Generate permanent rewrites based on current rewrites
+     *
+     * @param int $storeId
+     * @return array
+     */
+    protected function generateRewritesBasedOnCurrentRewrites($storeId)
+    {
+        $urls = [];
+        foreach ($this->urlMatcher->findAllByFilter($this->createCurrentUrlRewritesFilter($storeId)) as $url) {
+            $targetPath = null;
+            if ($url->getRedirectType()) {
+                $targetPath = str_replace(
+                    $this->product->getOrigData('url_key'),
+                    $this->product->getData('url_key'),
+                    $url->getTargetPath()
+                );
+                $redirectType = $url->getRedirectType();
+            } elseif ($this->product->getData('save_rewrites_history')) {
+                $targetPath = str_replace(
+                    $this->product->getOrigData('url_key'),
+                    $this->product->getData('url_key'),
+                    $url->getRequestPath()
+                );
+                $redirectType = OptionProvider::PERMANENT;
+            }
+
+            if ($targetPath && $url->getRequestPath() != $targetPath) {
+                $urls[] = $this->createUrlRewrite($storeId, $url->getRequestPath(), $targetPath, $redirectType);
+            }
+        }
+        return $urls;
+    }
+
+    /**
+     * @param int $storeId
+     * @return \Magento\UrlRedirect\Service\V1\Data\Filter
+     */
+    protected function createCurrentUrlRewritesFilter($storeId)
+    {
+        /** @var \Magento\UrlRedirect\Service\V1\Data\Filter $filter */
+        $filter = $this->filterFactory->create();
+
+        $filter->setStoreId($storeId);
+        $filter->setEntityId($this->product->getId());
+        $filter->setEntityType(self::ENTITY_TYPE_PRODUCT);
+        return $filter;
+    }
+
+    /**
+     * Get categories assigned to product
+     *
+     * @return \Magento\Catalog\Model\Resource\Category\Collection
+     */
+    protected function getCategories()
+    {
+        if (!$this->categories) {
+            $this->categories = $this->product->getCategoryCollection();
+            $this->categories->addAttributeToSelect('url_key');
+            $this->categories->addAttributeToSelect('url_path');
+        }
+        return $this->categories;
+    }
+
+    /**
+     * Create url rewrite object
+     *
+     * @param int $storeId
+     * @param string $requestPath
+     * @param string $targetPath
+     * @param string|null $redirectType Null or one of OptionProvider const
+     * @return \Magento\UrlRedirect\Service\V1\Data\UrlRewrite
+     */
+    protected function createUrlRewrite($storeId, $requestPath, $targetPath, $redirectType = null)
+    {
+        return $this->catalogUrlRewriteHelper->createUrlRewrite(
+            self::ENTITY_TYPE_PRODUCT,
+            $this->product->getId(),
+            $storeId,
+            $requestPath,
+            $targetPath,
+            $redirectType
+        );
+    }
+}
diff --git a/app/code/Magento/CatalogUrlRewrite/Service/V1/ProductUrlGeneratorInterface.php b/app/code/Magento/CatalogUrlRewrite/Service/V1/ProductUrlGeneratorInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..75daa35a4df708f764fcb2d4128b6a885f3315df
--- /dev/null
+++ b/app/code/Magento/CatalogUrlRewrite/Service/V1/ProductUrlGeneratorInterface.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CatalogUrlRewrite\Service\V1;
+
+/**
+ * Product Generator
+ */
+interface ProductUrlGeneratorInterface
+{
+    /**
+     * Generate list of urls
+     *
+     * @param \Magento\Catalog\Model\Product $product
+     * @return \Magento\UrlRedirect\Service\V1\Data\UrlRewrite[]
+     */
+    public function generate($product);
+
+    /**
+     * @param \Magento\Catalog\Model\Product $product
+     * @param \Magento\Catalog\Model\Category[] $changedCategories
+     * @return \Magento\UrlRedirect\Service\V1\Data\UrlRewrite[]
+     */
+    public function generateWithChangedCategories($product, $changedCategories);
+}
diff --git a/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/di.xml b/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/di.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7f2e29067ac836fa117e1645677497b8ebec9fb8
--- /dev/null
+++ b/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/di.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+    <preference for="Magento\CatalogUrlRewrite\Service\V1\ProductUrlGeneratorInterface" type="Magento\CatalogUrlRewrite\Service\V1\ProductUrlGenerator"/>
+    <preference for="Magento\CatalogUrlRewrite\Service\V1\CategoryUrlGeneratorInterface" type="Magento\CatalogUrlRewrite\Service\V1\CategoryUrlGenerator"/>
+</config>
diff --git a/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/events.xml b/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/events.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1b6588ba2931193f230cfc78ef32009049fe2bb6
--- /dev/null
+++ b/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/events.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/Event/etc/events.xsd">
+    <event name="catalog_product_save_after">
+        <observer name="process_url_rewrite_saving" instance="Magento\CatalogUrlRewrite\Model\Product\Observer" method="processUrlRewriteSaving"/>
+    </event>
+    <event name="catalog_category_save_after">
+        <observer name="process_url_rewrite_saving" instance="Magento\CatalogUrlRewrite\Model\Category\Observer" method="processUrlRewriteSaving"/>
+    </event>
+</config>
diff --git a/app/code/Magento/CatalogUrlRewrite/etc/module.xml b/app/code/Magento/CatalogUrlRewrite/etc/module.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1ff2849f6f22e96e533e60c75e483909077f2929
--- /dev/null
+++ b/app/code/Magento/CatalogUrlRewrite/etc/module.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+    <module name="Magento_CatalogUrlRewrite" schema_version="1.0.0.0" active="false">
+        <depends>
+            <module name="Magento_Catalog"/>
+            <module name="Magento_Eav"/>
+            <module name="Magento_Store"/>
+            <module name="Magento_UrlRedirect"/>
+        </depends>
+    </module>
+</config>
diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml
index e19ec443adb485dd4fdd099836c6ea48ce8a3b06..4108d230e9a531efe1e87629972edeb8c57e0f8d 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/cart/coupon.phtml
@@ -37,7 +37,7 @@
                 <div class="field">
                     <label for="coupon_code" class="label"><span><?php echo __('Enter your code') ?></span></label>
                     <div class="control">
-                        <input type="text" class="input-text" id="coupon_code" name="coupon_code" value="<?php echo $this->escapeHtml($this->getCouponCode()) ?>" />
+                        <input type="text" class="input-text" id="coupon_code" name="coupon_code" value="<?php echo $this->escapeHtml($this->getCouponCode()) ?>" placeholder="<?php echo $this->escapeHtml(__('Enter your code'));?>" />
                     </div>
                 </div>
                 <div class="actions-toolbar">
diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/form.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/form.phtml
index 30cc87289a9d382b1508dc9bfe6712b1a140d2fb..d6f57db2366577c59f8b139e2e3b75c977beb0dd 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/cart/form.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/cart/form.phtml
@@ -32,27 +32,19 @@
           data-mage-init='{"validation":{}}'
           class="form cart">
     <?php echo $this->getBlockHtml('formkey'); ?>
-    <div class="cart table wrapper<?php echo $mergedCells == 2 ? ' detailed' : ''; ?>">
+    <div class="cart table-wrapper<?php echo $mergedCells == 2 ? ' detailed' : ''; ?>">
         <table id="shopping-cart-table"
                class="cart items data"
                data-mage-init='{"shoppingCart":{"emptyCartButton": "action.clear",
-                                                "updateCartActionContainer": "#update_cart_action_container"}}'>
+               "updateCartActionContainer": "#update_cart_action_container"}}'>
             <caption><?php echo __('Shopping Cart Items') ?></caption>
             <thead>
                 <tr>
-                    <th class="col item" rowspan="<?php echo $mergedCells; ?>"><span><?php echo __('Item') ?></span></th>
-                    <th class="col price" colspan="<?php echo $mergedCells; ?>"><span><?php echo __('Unit Price') ?></span></th>
-                    <th class="col qty" rowspan="<?php echo $mergedCells; ?>"><span><?php echo __('Qty') ?></span></th>
-                    <th class="col subtotal" colspan="<?php echo $mergedCells; ?>"><span><?php echo __('Subtotal') ?></span></th>
+                    <th class="col item"><span><?php echo __('Item') ?></span></th>
+                    <th class="col price"><span><?php echo __('Price') ?></span></th>
+                    <th class="col qty"><span><?php echo __('Qty') ?></span></th>
+                    <th class="col subtotal"><span><?php echo __('Subtotal') ?></span></th>
                 </tr>
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()): ?>
-                <tr>
-                    <th class="col price excl tax"><?php echo $this->helper('Magento\Tax\Helper\Data')->getIncExcTaxLabel(false) ?></th>
-                    <th class="col price incl tax"><?php echo $this->helper('Magento\Tax\Helper\Data')->getIncExcTaxLabel(true) ?></th>
-                    <th class="col subtotal excl tax"><?php echo $this->helper('Magento\Tax\Helper\Data')->getIncExcTaxLabel(false) ?></th>
-                    <th class="col subtotal incl tax"><?php echo $this->helper('Magento\Tax\Helper\Data')->getIncExcTaxLabel(true) ?></th>
-                </tr>
-                <?php endif; ?>
             </thead>
             <?php foreach($this->getItems() as $_item): ?>
                 <?php echo $this->getItemHtml($_item) ?>
@@ -77,10 +69,3 @@
     </div>
 </form>
 <?php echo $this->getChildHtml('shopping.cart.table.after'); ?>
-<script type="text/javascript">
-    (function($) {
-        $('.cart-summary').mage('sticky', {
-            container: '.cart-container'
-        });
-    })(jQuery)
-</script>
diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/item/configure/updatecart.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/item/configure/updatecart.phtml
index 5ec4ce2d625ef110cecf29180b1406e962f3b276..8f2ea4fd355d080ec51e05f63483bed13e7a451d 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/cart/item/configure/updatecart.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/cart/item/configure/updatecart.phtml
@@ -60,5 +60,3 @@
         })(jQuery);
     </script>
 <?php endif; ?>
-
-
diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml
index 113d146ae00faab5a88d94647742bb76d32a3802..b6c4a68dd0aa340207fd25d07f9adb0bf19ff06b 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml
@@ -29,16 +29,16 @@ $isVisibleProduct = $_item->getProduct()->isVisibleInSiteVisibility();
 $canApplyMsrp = $this->helper('Magento\Catalog\Helper\Data')->canApplyMsrp($_item->getProduct(), \Magento\Catalog\Model\Product\Attribute\Source\Msrp\Type::TYPE_BEFORE_ORDER_CONFIRM);
 ?>
 <tbody class="cart item">
-<tr class="item info">
+<tr class="item info item-info">
     <td class="col item">
-        <?php if ($this->hasProductUrl()):?><a href="<?php echo $this->getProductUrl() ?>" title="<?php echo $this->escapeHtml($this->getProductName()) ?>" class="product photo">
+        <?php if ($this->hasProductUrl()):?><a href="<?php echo $this->getProductUrl() ?>" title="<?php echo $this->escapeHtml($this->getProductName()) ?>" class="product photo product-item-photo">
         <?php else:?>
-            <span class="product photo">
+            <span class="product photo product-item-photo">
         <?php endif;?>
         <?php echo $this->getLayout()->createBlock('Magento\Catalog\Block\Product\Image')->init($this->getProductForThumbnail(), 'cart_page_product_thumbnail')->toHtml(); ?>
         <?php if ($this->hasProductUrl()):?></a><?php else: ?></span><?php endif; ?>
-        <div class="product details">
-            <strong class="product name">
+        <div class="product details product-item-details">
+            <strong class="product name product-item-name">
             <?php if ($this->hasProductUrl()):?>
                 <a href="<?php echo $this->getProductUrl() ?>"><?php echo $this->escapeHtml($this->getProductName()) ?></a>
             <?php else: ?>
@@ -46,7 +46,7 @@ $canApplyMsrp = $this->helper('Magento\Catalog\Helper\Data')->canApplyMsrp($_ite
             <?php endif; ?>
             </strong>
             <?php if ($_options = $this->getOptionList()):?>
-            <dl class="cart item options">
+            <dl class="cart-item-options">
                 <?php foreach ($_options as $_option) : ?>
                 <?php $_formatedOptionValue = $this->getFormatedOptionValue($_option) ?>
                 <dt><?php echo $this->escapeHtml($_option['label']) ?></dt>
@@ -78,7 +78,7 @@ $canApplyMsrp = $this->helper('Magento\Catalog\Helper\Data')->canApplyMsrp($_ite
     </td>
 
     <?php if ($canApplyMsrp): ?>
-        <td class="col msrp"<?php if ($this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()): ?> colspan="2"<?php endif; ?>>
+        <td class="col msrp" data-th="<?php echo $this->escapeHtml(__('Price')); ?>">
             <span class="pricing msrp">
                 <span class="msrp notice"><?php echo __('See price before order confirmation.'); ?></span>
                 <?php $helpLinkId = 'cart-msrp-help-' . $_item->getId(); ?>
@@ -97,198 +97,201 @@ $canApplyMsrp = $this->helper('Magento\Catalog\Helper\Data')->canApplyMsrp($_ite
         </td>
     <?php else: ?>
 
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displayCartPriceExclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()): ?>
-        <td class="col price excl tax" data-th="<?php echo __('Unit Price Excl. Tax'); ?>">
+    <?php if ($this->helper('Magento\Tax\Helper\Data')->displayCartPriceExclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartPriceInclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()): ?>
+    <td class="col price" data-th="<?php echo $this->escapeHtml(__('Price')); ?>">
+    <?php if ($this->helper('Magento\Tax\Helper\Data')->displayCartPriceInclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()): ?>
+        <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
+        <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($_item); ?>
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                <span class="cart tax total" data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $_item->getId(); ?>"}'>
-            <?php else: ?>
-                <span class="cart price">
-            <?php endif; ?>
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getCalculationPrice()+$_item->getWeeeTaxAppliedAmount()+$_item->getWeeeTaxDisposition()); ?>
-                <?php else: ?>
-                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getCalculationPrice()) ?>
-                <?php endif; ?>
+            <span class="cart-tax-total"
+                  data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $_item->getId(); ?>"}'>
+        <?php else: ?>
+            <span class="cart price">
+        <?php endif; ?>
+
+        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+            <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedAmount()); ?>
+        <?php else: ?>
+            <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl-$_item->getWeeeTaxDisposition()) ?>
+        <?php endif; ?>
             </span>
 
             <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item)): ?>
-
-                <div class="cart tax info" id="eunit-item-tax-details<?php echo $_item->getId(); ?>" style="display:none;">
+                <div class="cart-tax-info" id="unit-item-tax-details<?php echo $_item->getId(); ?>" style="display: none;">
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
                         <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                            <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount'],true,true); ?></span>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount'],true,true); ?></span>
                         <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
                         <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                            <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount'],true,true); ?></span>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount_incl_tax'],true,true); ?></span>
                         <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
                         <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                            <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount'],true,true); ?></span>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount_incl_tax'],true,true); ?></span>
                         <?php endforeach; ?>
                     <?php endif; ?>
                 </div>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <div class="cart tax total" data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $_item->getId(); ?>"}'>
-                        <span class="weee"><?php echo __('Total'); ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getCalculationPrice()+$_item->getWeeeTaxAppliedAmount()+$_item->getWeeeTaxDisposition()); ?></span>
+                    <div class="cart-tax-total"
+                         data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $_item->getId(); ?>"}'>
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedAmount()); ?></span>
                     </div>
                 <?php endif; ?>
             <?php endif; ?>
-            <?php $cols++; ?>
-        </td>
+        </span>
+    <?php endif; ?>
 
+    <?php if ($this->helper('Magento\Tax\Helper\Data')->displayCartPriceExclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()): ?>
+        <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
+        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+            <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $_item->getId(); ?>"}'>
+        <?php else: ?>
+            <span class="cart price">
+        <?php endif; ?>
+        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+            <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getCalculationPrice() + $_item->getWeeeTaxAppliedAmount() + $_item->getWeeeTaxDisposition()); ?>
+        <?php else: ?>
+            <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getCalculationPrice()) ?>
         <?php endif; ?>
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displayCartPriceInclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()): ?>
-        <td class="col price incl tax" data-th="<?php echo __('Unit Price Incl. Tax'); ?>">
-            <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($_item); ?>
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                <span class="cart tax total" data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $_item->getId(); ?>"}'>
-            <?php else: ?>
-                <span class="cart price">
-            <?php endif; ?>
-
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedAmountInclTax()); ?>
-                <?php else: ?>
-                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl-$_item->getWeeeTaxDisposition()) ?>
-                <?php endif; ?>
-
             </span>
             <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item)): ?>
-
-                <div class="cart tax info" id="unit-item-tax-details<?php echo $_item->getId(); ?>" style="display:none;">
+                <div class="cart-tax-info" id="eunit-item-tax-details<?php echo $_item->getId(); ?>" style="display:none;">
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
                         <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                            <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount_incl_tax'],true,true); ?></span>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount'], true, true); ?></span>
                         <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
                         <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                            <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount_incl_tax'],true,true); ?></span>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount_incl_tax'], true, true); ?></span>
                         <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
                         <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                            <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount_incl_tax'],true,true); ?></span>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount_incl_tax'], true, true); ?></span>
                         <?php endforeach; ?>
                     <?php endif; ?>
                 </div>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <div class="cart tax total" data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $_item->getId(); ?>"}'>
-                        <span class="weee"><?php echo __('Total incl. tax'); ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedAmountInclTax()); ?></span>
+                    <div class="cart-tax-total"
+                         data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $_item->getId(); ?>"}'>
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getCalculationPrice() + $_item->getWeeeTaxAppliedAmount() + $_item->getWeeeTaxDisposition()); ?></span>
                     </div>
                 <?php endif; ?>
             <?php endif; ?>
-            <?php $cols++; ?>
-        </td>
-        <?php endif; ?>
+        </span>
+    <?php endif; ?>
+        <?php $cols++; ?>
+    </td>
+    <?php endif; ?>
+
     <?php endif; ?>
-    <td class="col qty">
+    <td class="col qty" data-th="<?php echo $this->escapeHtml(__('Qty')); ?>">
         <div class="control qty">
         <input name="cart[<?php echo $_item->getId() ?>][qty]" value="<?php echo $this->getQty() ?>" type="number" size="4" title="<?php echo __('Qty') ?>" class="input-text qty" maxlength="12" data-validate="{required:true,'validate-greater-than-zero':true}"/>
         </div>
         <?php $cols++; ?>
     </td>
-    <?php if (($this->helper('Magento\Tax\Helper\Data')->displayCartPriceExclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()) && !$_item->getNoSubtotal()): ?>
-    <td class="col subtotal excl tax" data-th="<?php echo __('Subtotal Excl. Tax'); ?>">
-        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-            <span class="cart tax total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
-        <?php else: ?>
-            <span class="cart price">
-        <?php endif; ?>
 
+    <?php if (($this->helper('Magento\Tax\Helper\Data')->displayCartPriceInclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartPriceExclTax() ||  $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()) && !$_item->getNoSubtotal()): ?>
+    <td class="col subtotal" data-th="<?php echo $this->escapeHtml(__('Subtotal'));?>">
+        <?php if (($this->helper('Magento\Tax\Helper\Data')->displayCartPriceInclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()) && !$_item->getNoSubtotal()): ?>
+        <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax'));?>">
+            <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($_item); ?>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
+            <?php else: ?>
+                <span class="cart price">
+            <?php endif; ?>
             <?php if ($canApplyMsrp): ?>
                 <span class="cart msrp subtotal">--</span>
             <?php else: ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getRowTotal()+$_item->getWeeeTaxAppliedRowAmount()+$_item->getWeeeTaxRowDisposition()); ?>
+                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedRowAmount()); ?>
                 <?php else: ?>
-                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getRowTotal()) ?>
+                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl-$_item->getWeeeTaxRowDisposition()) ?>
                 <?php endif; ?>
             <?php endif; ?>
+            </span>
 
-        </span>
-        <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item)): ?>
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item)): ?>
+                <div class="cart-tax-info" id="subtotal-item-tax-details<?php echo $_item->getId(); ?>" style="display:none;">
+                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount'],true,true); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount_incl_tax'],true,true); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount_incl_tax'],true,true); ?></span>
+                        <?php endforeach; ?>
+                    <?php endif; ?>
+                </div>
 
-            <div class="cart tax info" id="esubtotal-item-tax-details<?php echo $_item->getId(); ?>" style="display:none;">
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                        <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount'],true,true); ?></span>
-                    <?php endforeach; ?>
-                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                        <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount'],true,true); ?></span>
-                    <?php endforeach; ?>
-                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                        <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount'],true,true); ?></span>
-                    <?php endforeach; ?>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                    <div class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
+                        <span class="weee" data-th="<?php echo __('Total incl. tax'); ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedRowAmount()); ?></span>
+                    </div>
                 <?php endif; ?>
-            </div>
-
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                <div class="cart tax total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
-                    <span class="weee"><?php echo __('Total'); ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getRowTotal()+$_item->getWeeeTaxAppliedRowAmount()+$_item->getWeeeTaxRowDisposition()); ?></span>
-                </div>
             <?php endif; ?>
-        <?php endif; ?>
-        <?php $cols++; ?>
-    </td>
-    <?php endif; ?>
-    <?php if (($this->helper('Magento\Tax\Helper\Data')->displayCartPriceInclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()) && !$_item->getNoSubtotal()): ?>
-    <td class="col subtotal incl tax" data-th="<?php echo __('Subtotal Incl. Tax'); ?>">
-        <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($_item); ?>
-        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-            <span class="cart tax total" data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
-        <?php else: ?>
-            <span class="cart price">
+            </span>
         <?php endif; ?>
 
+        <?php if (($this->helper('Magento\Tax\Helper\Data')->displayCartPriceExclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()) && !$_item->getNoSubtotal()): ?>
+        <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax'));?>">
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
+            <?php else: ?>
+                <span class="cart price">
+            <?php endif; ?>
             <?php if ($canApplyMsrp): ?>
                 <span class="cart msrp subtotal">--</span>
             <?php else: ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedRowAmountInclTax()); ?>
+                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getRowTotal()+$_item->getWeeeTaxAppliedRowAmount()+$_item->getWeeeTaxRowDisposition()); ?>
                 <?php else: ?>
-                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl-$_item->getWeeeTaxRowDisposition()) ?>
+                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getRowTotal()) ?>
                 <?php endif; ?>
             <?php endif; ?>
+            </span>
 
-        </span>
-
-
-        <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item)): ?>
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item)): ?>
+                <div class="cart-tax-info" id="esubtotal-item-tax-details<?php echo $_item->getId(); ?>" style="display:none;">
+                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount'],true,true); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount_incl_tax'],true,true); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount_incl_tax'],true,true); ?></span>
+                        <?php endforeach; ?>
+                    <?php endif; ?>
+                </div>
 
-            <div class="cart tax info" id="subtotal-item-tax-details<?php echo $_item->getId(); ?>" style="display:none;">
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                        <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount_incl_tax'],true,true); ?></span>
-                    <?php endforeach; ?>
-                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                        <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount_incl_tax'],true,true); ?></span>
-                    <?php endforeach; ?>
-                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                        <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount_incl_tax'],true,true); ?></span>
-                    <?php endforeach; ?>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                    <div class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
+                        <span class="weee" data-th="<?php echo __('Total'); ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getRowTotal()+$_item->getWeeeTaxAppliedRowAmount()+$_item->getWeeeTaxRowDisposition()); ?></span>
+                    </div>
                 <?php endif; ?>
-            </div>
-
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                <div class="cart tax total" data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
-                    <span class="weee"><?php echo __('Total incl. tax'); ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedRowAmountInclTax()); ?></span>
-                </div>
             <?php endif; ?>
+        </span>
         <?php endif; ?>
         <?php $cols++; ?>
     </td>
     <?php endif; ?>
 </tr>
-<tr class="item actions">
+<tr class="item actions item-actions">
     <td colspan="<?php echo $cols;?>">
         <div class="actions">
-
             <?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllowInCart()) : ?>
                 <?php if ($isVisibleProduct): ?>
                 <a href="#" data-post='<?php echo $this->helper('Magento\Wishlist\Helper\Data')->getMoveFromCartParams($_item->getId()); ?>' class="use-ajax action towishlist">
diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/methods.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/methods.phtml
index 56379e7a857ed6d0c18d8ba64d453993f9b4de63..30509d55c06f130af30d626a77172b63935d000f 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/cart/methods.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/cart/methods.phtml
@@ -27,7 +27,7 @@
 ?>
 <?php if(!$this->hasError()): ?>
 <?php $methods = $this->getMethods('methods') ? : $this->getMethods('top_methods') ?>
-<ul class="checkout methods items">
+<ul class="checkout methods items checkout-methods-items">
 <?php foreach ($methods as $method): ?>
     <?php if ($methodHtml = $this->getMethodHtml($method)): ?>
     <li class="item"><?php echo $methodHtml; ?></li>
diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/noItems.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/noItems.phtml
index 386c6c249dbed68ab3db79bd179de85766d70e6d..dad5681619f5cd60bbef06c728a84d441782a72f 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/cart/noItems.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/cart/noItems.phtml
@@ -24,7 +24,7 @@
 
 /**  @var $this \Magento\Checkout\Block\Cart */
 ?>
-<div class="cart empty">
+<div class="cart-empty">
     <?php echo $this->getChildHtml('checkout_cart_empty_widget'); ?>
     <p><?php echo __('You have no items in your shopping cart.') ?></p>
     <p><?php echo __('Click <a href="%1">here</a> to continue shopping.', $this->getContinueShoppingUrl()) ?></p>
diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/shipping.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/shipping.phtml
index 60e0be53b1696aa69733037843bbdaa4326c29a0..90e954f4e40e033c3279bfc0abb810423b5d3229 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/cart/shipping.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/cart/shipping.phtml
@@ -57,7 +57,7 @@
             <div class="field postcode<?php if ($this->isZipCodeRequired()) echo ' required' ?>">
                 <label for="postcode" class="label"><span><?php echo __('Zip/Postal Code') ?></span></label>
                 <div class="control">
-                    <input class="input-text" data-validate="{<?php if ($this->isZipCodeRequired()):?> 'required-entry':true,<?php endif;?>'validate-zip':true}" type="text" id="postcode" name="estimate_postcode" value="<?php echo $this->escapeHtml($this->getEstimatePostcode()) ?>" />
+                    <input class="input-text" data-validate="{<?php if ($this->isZipCodeRequired()):?> 'required-entry':true,<?php endif;?>'validate-zip-international':true}" type="text" id="postcode" name="estimate_postcode" value="<?php echo $this->escapeHtml($this->getEstimatePostcode()) ?>" />
                 </div>
             </div>
             <div class="actions-toolbar">
@@ -88,8 +88,8 @@
         <fieldset class="fieldset rates">
             <dl class="items methods">
                 <?php foreach ($_shippingRateGroups as $code => $_rates): ?>
-                    <dt class="item title"><span><?php echo $this->escapeHtml($this->getCarrierName($code)) ?></span></dt>
-                    <dd class="item options">
+                    <dt class="item-title"><span><?php echo $this->escapeHtml($this->getCarrierName($code)) ?></span></dt>
+                    <dd class="item-options">
                     <?php foreach ($_rates as $_rate): ?>
                         <div
                             class="<?php if ($_rate->getErrorMessage()): echo ' message error'; else: echo 'field choice item'; endif; ?>">
diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/sidebar/default.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/sidebar/default.phtml
index 3ab2e4df3ed6e9c948d983a867d2d038c4712784..13f9c393be0a0a320dd5231253f560321784587e 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/cart/sidebar/default.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/cart/sidebar/default.phtml
@@ -27,14 +27,14 @@
 <?php $_item = $this->getItem() ?>
 <?php $canApplyMsrp = $this->helper('Magento\Catalog\Helper\Data')->canApplyMsrp($_item->getProduct(), \Magento\Catalog\Model\Product\Attribute\Source\Msrp\Type::TYPE_BEFORE_ORDER_CONFIRM); ?>
 <?php $imageBlock =  $this->getLayout()->createBlock('Magento\Catalog\Block\Product\Image')?>
-<li class="item product">
+<li class="item product product-item">
 <div class="product">
     <?php if ($this->hasProductUrl()): ?>
-        <a href="<?php echo $this->getProductUrl()?>" title="<?php echo $this->escapeHtml($this->getProductName()) ?>" class="product photo">
+        <a href="<?php echo $this->getProductUrl()?>" title="<?php echo $this->escapeHtml($this->getProductName()) ?>" class="product photo product-item-photo">
             <?php echo $imageBlock->init($this->getProductForThumbnail(), 'mini_cart_product_thumbnail')->toHtml() ?>
         </a>
     <?php else: ?>
-        <span class="product photo">
+        <span class="product photo product-item-photo">
             <?php echo $imageBlock->init($this->getProductForThumbnail(), 'mini_cart_product_thumbnail')->toHtml() ?>
         </span>
     <?php endif; ?>
diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/login.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/login.phtml
index 71ba691841e03aab7d4eca86d684b600f8a7c845..5d50197db264553264b91798f59038dd96830d32 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/onepage/login.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/onepage/login.phtml
@@ -97,12 +97,10 @@
 
         <?php if( $this->isAllowedGuestCheckout() ): ?>
             <fieldset class="fieldset guest">
-                <?php if( $this->isAllowedGuestCheckout() ): ?>
                 <div class="field choice">
                     <input type="radio" name="checkout_method" data-role="checkout-method-guest" id="login:guest" value="guest"<?php if($this->getQuote()->getCheckoutMethod()==Magento\Checkout\Model\Type\Onepage::METHOD_GUEST): ?> checked="checked"<?php endif; ?> class="radio" />
                     <label class="label" for="login:guest"><span><?php echo __('Checkout as Guest') ?></span></label>
                 </div>
-                <?php endif; ?>
                 <?php if( $this->helper('Magento\Customer\Helper\Data')->isRegistrationAllowed() ): ?>
                 <div class="field choice">
                     <input type="radio" name="checkout_method" data-role="checkout-method-register" id="login:register" value="register"<?php if($this->getQuote()->getCheckoutMethod()==Magento\Checkout\Model\Type\Onepage::METHOD_REGISTER || !$this->isAllowedGuestCheckout()): ?> checked="checked"<?php endif ?> class="radio" />
@@ -110,21 +108,21 @@
                 </div>
                 <?php endif; ?>
             </fieldset>
-        <?php else: ?>
-            <input type="hidden" name="checkout_method" id="login:register" value="register" checked="checked" />
         <?php endif; ?>
-        <div class="actions-toolbar">
+        <div class="actions toolbar">
             <div class="primary">
                 <?php if ($this->isAllowedGuestCheckout()): ?>
                     <button data-role="opc-continue" id="onepage-guest-register-button" type="button" class="action continue primary" data-checkout='{"isGuestCheckoutAllowed":true}'><span><?php echo __('Continue') ?></span></button>
                 <?php elseif ($this->helper('Magento\Checkout\Helper\Data')->isCustomerMustBeLogged()): ?>
+                    <input type="hidden" name="checkout_method" id="login:register" value="register" checked="checked" />
                     <button data-role="opc-continue" id="onepage-guest-register-button" type="button" class="action register primary" data-checkout='{"isGuestCheckoutAllowed":false, "registrationUrl":"<?php echo $this->helper('Magento\Customer\Helper\Data')->getRegisterUrl();?>"}'><span><?php echo __('Register') ?></span></button>
                 <?php else: ?>
-                    <input type="hidden" name="checkout_method" id="login:register" value="register" checked="checked" />
+                    <input type="hidden" name="checkout_method" data-role="checkout-method-register" id="login:register" value="register" checked="checked" />
                     <button data-role="opc-continue" id="onepage-guest-register-button" type="button" class="action register primary" data-checkout='{"isGuestCheckoutAllowed":true}'><span><?php echo __('Register') ?></span></button>
                 <?php endif; ?>
             </div>
         </div>
+
     </div>
 </div>
 <?php endif; ?>
diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/info.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/review/info.phtml
index 3fd1100c57e5f5a0372b9dae863c6e133e7c4c85..9c541610eccb00a6b49971d5f580657b5f5557cc 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/info.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/onepage/review/info.phtml
@@ -25,7 +25,7 @@
 /** @var $this \Magento\Checkout\Block\Onepage\Review\Info */
 ?>
 <?php echo $this->getChildHtml('items_before'); ?>
-<div id="checkout-review-table-wrapper" class="review table wrapper">
+<div id="checkout-review-table-wrapper" class="review table-wrapper">
     <?php if ($this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()): $colspan = $rowspan = 2; else: $colspan = $rowspan = 1; endif; ?>
     <table class="data table order review items" id="checkout-review-table">
         <caption>Order Review</caption>
diff --git a/app/code/Magento/Checkout/view/frontend/templates/total/tax.phtml b/app/code/Magento/Checkout/view/frontend/templates/total/tax.phtml
index 925a5586c12443e64286bb2abe583c6157d64dbf..7689b84c361a67338d8299d53aeda2d2d92ad1b5 100644
--- a/app/code/Magento/Checkout/view/frontend/templates/total/tax.phtml
+++ b/app/code/Magento/Checkout/view/frontend/templates/total/tax.phtml
@@ -23,39 +23,11 @@
  */
 ?>
 <?php global $taxIter; $taxIter++; ?>
-<?php if ($this->helper('Magento\Tax\Helper\Data')->displayFullSummary() && $this->getTotal()->getValue()!=0): ?>
-<?php $isTop = 1; ?>
-            <?php foreach ($this->getTotal()->getFullInfo() as $info): ?>
-                <?php if (isset($info['hidden']) && $info['hidden']) continue; ?>
-                <?php $percent = $info['percent']; ?>
-                <?php $amount = $info['amount']; ?>
-                <?php $rates = $info['rates']; ?>
-                <?php $isFirst = 1; ?>
 
-                <?php foreach ($rates as $rate): ?>
-                <tr class="totals tax details details-<?php echo $taxIter; ?>">
-                    <td class="mark" style="<?php echo $this->getTotal()->getStyle() ?>" colspan="<?php echo $this->getColspan(); ?>">
-                        <?php echo $this->escapeHtml($rate['title']); ?>
-                        <?php if (!is_null($rate['percent'])): ?>
-                            (<?php echo (float)$rate['percent']; ?>%)
-                        <?php endif; ?>
-                        <br />
-                    </td>
-                    <?php if ($isFirst): ?>
-                        <td class="amount" rowspan="<?php echo count($rates); ?>" class="a-right" style="<?php echo $this->getTotal()->getStyle() ?>">
-                            <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($amount); ?>
-                        </td>
-                    <?php endif; ?>
-                </tr>
-                <?php $isFirst = 0; ?>
-                <?php $isTop = 0; ?>
-                <?php endforeach; ?>
-            <?php endforeach; ?>
-<?php endif;?>
 <?php
-    $attributes = 'class="totals tax"';
+    $attributes = 'class="totals-tax"';
     if ($this->helper('Magento\Tax\Helper\Data')->displayFullSummary() && $this->getTotal()->getValue()!=0) {
-        $attributes = 'class="totals tax summary"';
+        $attributes = 'class="totals-tax-summary"';
     }
 ?>
 <tr <?php echo $attributes; ?>>
@@ -70,3 +42,33 @@
         <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($this->getTotal()->getValue()) ?>
     </td>
 </tr>
+
+<?php if ($this->helper('Magento\Tax\Helper\Data')->displayFullSummary() && $this->getTotal()->getValue()!=0): ?>
+    <?php $isTop = 1; ?>
+    <?php foreach ($this->getTotal()->getFullInfo() as $info): ?>
+        <?php if (isset($info['hidden']) && $info['hidden']) continue; ?>
+        <?php $percent = $info['percent']; ?>
+        <?php $amount = $info['amount']; ?>
+        <?php $rates = $info['rates']; ?>
+        <?php $isFirst = 1; ?>
+
+        <?php foreach ($rates as $rate): ?>
+            <tr class="totals tax details details-<?php echo $taxIter; ?>">
+                <td class="mark" style="<?php echo $this->getTotal()->getStyle() ?>" colspan="<?php echo $this->getColspan(); ?>">
+                    <?php echo $this->escapeHtml($rate['title']); ?>
+                    <?php if (!is_null($rate['percent'])): ?>
+                        (<?php echo (float)$rate['percent']; ?>%)
+                    <?php endif; ?>
+                    <br />
+                </td>
+                <?php if ($isFirst): ?>
+                    <td class="amount" rowspan="<?php echo count($rates); ?>" style="<?php echo $this->getTotal()->getStyle() ?>">
+                        <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($amount); ?>
+                    </td>
+                <?php endif; ?>
+            </tr>
+            <?php $isFirst = 0; ?>
+            <?php $isTop = 0; ?>
+        <?php endforeach; ?>
+    <?php endforeach; ?>
+<?php endif;?>
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/opc-checkout-method.js b/app/code/Magento/Checkout/view/frontend/web/js/opc-checkout-method.js
index b104a0425b0372c9829aa274f6bb118776d80607..483a9a4781be7a54585185319f6c59c3e00d4911 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/opc-checkout-method.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/opc-checkout-method.js
@@ -161,19 +161,35 @@
          * @return {Boolean}
          */
         _continue: function(elem) {
-            var json = elem.data('checkout');
+            var json            = elem.data('checkout'),
+                checkout        = this.options.checkout,
+                guestChecked    = $( checkout.loginGuestSelector ).is( ':checked' ),
+                loginRegister   = $( checkout.loginRegisterSelector )[0],
+                method          = 'register',
+                action          = 'show';
+            
             if (json.isGuestCheckoutAllowed) {
-                if ($(this.options.checkout.loginGuestSelector).is(':checked')) {
-                    this._ajaxContinue(this.options.checkout.saveUrl, {method:'guest'}, this.options.billingSection);
-                    this.element.find(this.options.checkout.registerCustomerPasswordSelector).hide();
-                } else if ($(this.options.checkout.loginRegisterSelector).is(':checked')) {
-                    this._ajaxContinue(this.options.checkout.saveUrl, {method:'register'}, this.options.billingSection);
-                    this.element.find(this.options.checkout.registerCustomerPasswordSelector).show();
-                } else {
-                    alert($.mage.__('Please choose to register or to checkout as a guest.'));
+                
+                if( !guestChecked && !(loginRegister && loginRegister.checked) ){
+                    alert( $.mage.__('Please choose to register or to checkout as a guest.') );
+                    
                     return false;
                 }
+
+                if( guestChecked ){
+                    method = 'guest';
+                    action = 'hide';
+                }
+
+                this._ajaxContinue(
+                    checkout.saveUrl,
+                    { method: method },
+                    this.options.billingSection
+                );
+
+                this.element.find( checkout.registerCustomerPasswordSelector )[action]();
             }
+
             this.element.trigger('login');
         },
 
diff --git a/app/code/Magento/CheckoutAgreements/Controller/Adminhtml/Agreement/Save.php b/app/code/Magento/CheckoutAgreements/Controller/Adminhtml/Agreement/Save.php
index 24073ded5ab984ff14becf1cf3a8d504e578d2ec..69ebc01f68567846811c1eaa5b8f2bd1e650417e 100644
--- a/app/code/Magento/CheckoutAgreements/Controller/Adminhtml/Agreement/Save.php
+++ b/app/code/Magento/CheckoutAgreements/Controller/Adminhtml/Agreement/Save.php
@@ -37,12 +37,17 @@ class Save extends \Magento\CheckoutAgreements\Controller\Adminhtml\Agreement
             $model->setData($postData);
 
             try {
-                $model->save();
-
-                $this->messageManager->addSuccess(__('The condition has been saved.'));
-                $this->_redirect('checkout/*/');
-
-                return;
+                $validationResult = $model->validateData(new \Magento\Framework\Object($postData));
+                if ($validationResult !== true) {
+                    foreach ($validationResult as $message) {
+                        $this->messageManager->addError($message);
+                    }
+                } else {
+                    $model->save();
+                    $this->messageManager->addSuccess(__('The condition has been saved.'));
+                    $this->_redirect('checkout/*/');
+                    return;
+                }
             } catch (\Magento\Framework\Model\Exception $e) {
                 $this->messageManager->addError($e->getMessage());
             } catch (\Exception $e) {
diff --git a/app/code/Magento/CheckoutAgreements/Model/Agreement.php b/app/code/Magento/CheckoutAgreements/Model/Agreement.php
index 009cadb5696204c1a68b8c7e374c3ce445a73e7b..c62dd5167d1c340ac46485d927091b68d726a5be 100644
--- a/app/code/Magento/CheckoutAgreements/Model/Agreement.php
+++ b/app/code/Magento/CheckoutAgreements/Model/Agreement.php
@@ -42,6 +42,13 @@ namespace Magento\CheckoutAgreements\Model;
  */
 class Agreement extends \Magento\Framework\Model\AbstractModel
 {
+    /**
+     * Allowed CSS units for height field
+     *
+     * @var array
+     */
+    protected $allowedCssUnits = array('px', 'pc', 'pt', 'ex', 'em', 'mm', 'cm', 'in', '%');
+
     /**
      * @return void
      */
@@ -49,4 +56,43 @@ class Agreement extends \Magento\Framework\Model\AbstractModel
     {
         $this->_init('Magento\CheckoutAgreements\Model\Resource\Agreement');
     }
+
+    /**
+     * @param \Magento\Framework\Object $agreementData
+     * @return array|bool
+     */
+    public function validateData($agreementData)
+    {
+        $errors = [];
+
+        $contentHeight = $agreementData->getContentHeight();
+        if ($contentHeight !== ''
+            && !preg_match('/^[0-9]*\.*[0-9]+(' . implode("|", $this->allowedCssUnits) . ')?$/', $contentHeight)
+        ) {
+            $errors[] = "Please input a valid CSS-height. For example 100px or 77pt or 20em or .5ex or 50%.";
+        }
+
+        return (count($errors)) ? $errors : true;
+    }
+
+    /**
+     * Processing object before save data
+     *
+     * @return $this
+     */
+    protected function _beforeSave()
+    {
+        if ($this->getContentHeight() == 0) {
+            $this->setContentHeight(''); //converting zero Content-Height
+        }
+
+        if ($this->getContentHeight()
+            && !preg_match('/('. implode("|", $this->allowedCssUnits) . ')/', $this->getContentHeight())
+        ) {
+            $contentHeight = $this->getContentHeight() . 'px'; //setting default units for Content-Height
+            $this->setContentHeight($contentHeight);
+        }
+
+        return parent::_beforeSave();
+    }
 }
diff --git a/app/code/Magento/CheckoutAgreements/i18n/en_US.csv b/app/code/Magento/CheckoutAgreements/i18n/en_US.csv
index 64927202823e9ca19f4b2082acf8b48a0b675e62..b5db8f403645334ceaec1080ed9a4ce55ba9ac07 100644
--- a/app/code/Magento/CheckoutAgreements/i18n/en_US.csv
+++ b/app/code/Magento/CheckoutAgreements/i18n/en_US.csv
@@ -30,3 +30,4 @@ Sales,Sales
 "Checkout Conditions","Checkout Conditions"
 "Checkout Terms and Conditions","Checkout Terms and Conditions"
 "Enable Terms and Conditions","Enable Terms and Conditions"
+"Please input a valid CSS-height. For example 100px or 77pt or 20em or .5ex or 50%.","Please input a valid CSS-height. For example 100px or 77pt or 20em or .5ex or 50%."
diff --git a/app/code/Magento/Cms/Model/Resource/Block/Grid/Collection.php b/app/code/Magento/Cms/Model/Resource/Block/Grid/Collection.php
index f22e1ec4bcdbedcd42f764b73d8b7dc802c53783..151b002fe6a7f437df1ddc24fcee67b2a5d7aa9b 100644
--- a/app/code/Magento/Cms/Model/Resource/Block/Grid/Collection.php
+++ b/app/code/Magento/Cms/Model/Resource/Block/Grid/Collection.php
@@ -37,14 +37,15 @@ class Collection extends \Magento\Cms\Model\Resource\Block\Collection
     }
 
     /**
-     * @param string $field
-     * @param null $condition
+     * @param string|array $field
+     * @param string|int|array|null $condition
      * @return \Magento\Cms\Model\Resource\Block\Grid\Collection
      */
     public function addFieldToFilter($field, $condition = null)
     {
         if ($field == 'store_id') {
-            return $this->addStoreFilter($field);
+            return $this->addStoreFilter($condition, false);
         }
+        return parent::addFieldToFilter($field, $condition);
     }
 }
diff --git a/app/code/Magento/CmsUrlRewrite/Model/Observer.php b/app/code/Magento/CmsUrlRewrite/Model/Observer.php
new file mode 100644
index 0000000000000000000000000000000000000000..e5278ac34beb11a2c2cd5176ce9e47c192e7f89e
--- /dev/null
+++ b/app/code/Magento/CmsUrlRewrite/Model/Observer.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CmsUrlRewrite\Model;
+
+use Magento\Framework\Event\Observer as EventObserver;
+use Magento\CmsUrlRewrite\Service\V1\CmsPageUrlGeneratorInterface;
+use Magento\UrlRedirect\Service\V1\UrlSaveInterface;
+use Magento\Framework\Model\Exception;
+
+class Observer
+{
+    /**
+     * @var CmsPageUrlGeneratorInterface
+     */
+    protected $urlGenerator;
+
+    /**
+     * @var \Magento\UrlRedirect\Service\V1\UrlSaveInterface
+     */
+    protected $urlSave;
+
+    /**
+     * @param CmsPageUrlGeneratorInterface $urlGenerator
+     * @param UrlSaveInterface $urlSave
+     */
+    public function __construct(CmsPageUrlGeneratorInterface $urlGenerator, UrlSaveInterface $urlSave)
+    {
+        $this->urlGenerator = $urlGenerator;
+        $this->urlSave = $urlSave;
+    }
+
+    /**
+     * Generate urls for UrlRewrite and save it in storage
+     *
+     * @param \Magento\Framework\Event\Observer $observer
+     * @return void
+     * @throws Exception|\Exception
+     */
+    public function processUrlRewriteSaving(EventObserver $observer)
+    {
+        /** @var $cmsPage \Magento\Cms\Model\Page */
+        $cmsPage = $observer->getEvent()->getObject();
+        if ($cmsPage->getOrigData('identifier') !== $cmsPage->getData('identifier')) {
+            $urls = $this->urlGenerator->generate($cmsPage);
+            try {
+                $this->urlSave->save($urls);
+            } catch (\Exception $e) {
+                if ($e->getCode() === 23000) { // Integrity constraint violation: 1062 Duplicate entry
+                    throw new Exception(__('A page URL key for specified store already exists.'));
+                }
+                throw $e;
+            }
+        }
+    }
+}
diff --git a/app/code/Magento/CmsUrlRewrite/Service/V1/CmsPageUrlGenerator.php b/app/code/Magento/CmsUrlRewrite/Service/V1/CmsPageUrlGenerator.php
new file mode 100644
index 0000000000000000000000000000000000000000..eda0815e280a78a810040769996f8119177ddea8
--- /dev/null
+++ b/app/code/Magento/CmsUrlRewrite/Service/V1/CmsPageUrlGenerator.php
@@ -0,0 +1,130 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CmsUrlRewrite\Service\V1;
+
+use Magento\Store\Model\StoreManagerInterface;
+use Magento\UrlRedirect\Service\V1\Data\Converter;
+use Magento\UrlRedirect\Service\V1\Data\UrlRewrite;
+
+class CmsPageUrlGenerator implements CmsPageUrlGeneratorInterface
+{
+    /**
+     * Entity type code
+     */
+    const ENTITY_TYPE = 'cms-page';
+
+    /**
+     * @var Converter
+     */
+    protected $converter;
+
+    /**
+     * Store manager
+     *
+     * @var StoreManagerInterface
+     */
+    protected $storeManager;
+
+    /**
+     * @var \Magento\Cms\Model\Page
+     */
+    protected $cmsPage;
+
+    /**
+     * @param Converter $converter
+     * @param StoreManagerInterface $storeManager
+     */
+    public function __construct(
+        Converter $converter,
+        StoreManagerInterface $storeManager
+    ) {
+        $this->converter = $converter;
+        $this->storeManager = $storeManager;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function generate($cmsPage)
+    {
+        $stores = $cmsPage->getStores();
+        $this->cmsPage = $cmsPage;
+        $urls = array_search('0', $stores) === false ? $this->generateForSpecificStores($stores)
+            : $this->generateForAllStores();
+        $this->cmsPage = null;
+        return $urls;
+    }
+
+    /**
+     * Generate list of urls for default store
+     *
+     * @return UrlRewrite[]
+     */
+    protected function generateForAllStores()
+    {
+        $urls = [];
+        foreach ($this->storeManager->getStores() as $store) {
+            $urls[] = $this->createUrlRewrite($store->getStoreId());
+        }
+        return $urls;
+    }
+
+    /**
+     * Generate list of urls per store
+     *
+     * @param int[] $storeIds
+     * @return UrlRewrite[]
+     */
+    protected function generateForSpecificStores($storeIds)
+    {
+        $urls = [];
+        $existingStores = $this->storeManager->getStores();
+        foreach ($storeIds as $storeId) {
+            if (!isset($existingStores[$storeId])) {
+                continue;
+            }
+            $urls[] = $this->createUrlRewrite($storeId);
+        }
+        return $urls;
+    }
+
+    /**
+     * Create url rewrite object
+     *
+     * @param int $storeId
+     * @param string|null $redirectType Null or one of OptionProvider const
+     * @return UrlRewrite
+     */
+    protected function createUrlRewrite($storeId, $redirectType = null)
+    {
+        return $this->converter->convertArrayToObject([
+            UrlRewrite::ENTITY_TYPE => self::ENTITY_TYPE,
+            UrlRewrite::ENTITY_ID => $this->cmsPage->getId(),
+            UrlRewrite::STORE_ID => $storeId,
+            UrlRewrite::REQUEST_PATH => $this->cmsPage->getIdentifier(),
+            UrlRewrite::TARGET_PATH => 'cms/page/view/page_id/' . $this->cmsPage->getId(),
+            UrlRewrite::REDIRECT_TYPE => $redirectType,
+        ]);
+    }
+}
diff --git a/app/code/Magento/CmsUrlRewrite/Service/V1/CmsPageUrlGeneratorInterface.php b/app/code/Magento/CmsUrlRewrite/Service/V1/CmsPageUrlGeneratorInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..a1b81e914ce91dbd17a7d29988784338f3429cd6
--- /dev/null
+++ b/app/code/Magento/CmsUrlRewrite/Service/V1/CmsPageUrlGeneratorInterface.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CmsUrlRewrite\Service\V1;
+
+/**
+ * Product Generator
+ */
+interface CmsPageUrlGeneratorInterface
+{
+    /**
+     * Generate list of urls
+     *
+     * @param \Magento\Cms\Model\Page $cmsPage
+     * @return \Magento\UrlRedirect\Service\V1\Data\UrlRewrite[]
+     */
+    public function generate($cmsPage);
+}
diff --git a/app/code/Magento/UrlRewrite/etc/config.xml b/app/code/Magento/CmsUrlRewrite/etc/adminhtml/di.xml
similarity index 80%
rename from app/code/Magento/UrlRewrite/etc/config.xml
rename to app/code/Magento/CmsUrlRewrite/etc/adminhtml/di.xml
index 0a3ac66124610c9df411ff79cf9cf66a4ae092aa..8f4ed44ca657e545f4e0524534d11bae41f17a41 100644
--- a/app/code/Magento/UrlRewrite/etc/config.xml
+++ b/app/code/Magento/CmsUrlRewrite/etc/adminhtml/di.xml
@@ -23,12 +23,6 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Core/etc/config.xsd">
-    <default>
-        <web>
-            <seo>
-                <use_rewrites>0</use_rewrites>
-            </seo>
-        </web>
-    </default>
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+    <preference for="Magento\CmsUrlRewrite\Service\V1\CmsPageUrlGeneratorInterface" type="Magento\CmsUrlRewrite\Service\V1\CmsPageUrlGenerator"/>
 </config>
diff --git a/app/code/Magento/CmsUrlRewrite/etc/adminhtml/events.xml b/app/code/Magento/CmsUrlRewrite/etc/adminhtml/events.xml
new file mode 100644
index 0000000000000000000000000000000000000000..49aaf665802d9eef2983ec116f3779488b141df6
--- /dev/null
+++ b/app/code/Magento/CmsUrlRewrite/etc/adminhtml/events.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/Event/etc/events.xsd">
+    <event name="cms_page_save_after">
+        <observer name="process_url_rewrite_saving" instance="Magento\CmsUrlRewrite\Model\Observer" method="processUrlRewriteSaving" />
+    </event>
+</config>
diff --git a/app/code/Magento/CmsUrlRewrite/etc/module.xml b/app/code/Magento/CmsUrlRewrite/etc/module.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8df04efdd0440c97e3c5324681c1ef535259fa43
--- /dev/null
+++ b/app/code/Magento/CmsUrlRewrite/etc/module.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+    <module name="Magento_CmsUrlRewrite" schema_version="1.0.0.0" active="false">
+        <depends>
+            <module name="Magento_Store"/>
+            <module name="Magento_UrlRedirect"/>
+        </depends>
+    </module>
+</config>
diff --git a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config.php b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config.php
index bc628d19e76ade2264d39a9e09772bf31843ff8f..a27a2dec5b0965ba4b255a6f194b4fef774e1618 100644
--- a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config.php
+++ b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config.php
@@ -257,15 +257,14 @@ class Config extends Widget implements TabInterface
             $productData = (array)$this->getRequest()->getParam('product');
             if (isset($productData['configurable_attributes_data'])) {
                 $configurableData = $productData['configurable_attributes_data'];
-                foreach ($attributes as $key => &$attribute) {
+                foreach ($attributes as $key => $attribute) {
                     if (isset($configurableData[$key])) {
-                        $attribute['values'] = array_merge(
+                        $attributes[$key] = array_replace_recursive($attribute, $configurableData[$key]);
+                        $attributes[$key]['values'] = array_merge(
                             isset($attribute['values']) ? $attribute['values'] : array(),
-                            isset(
-                                $configurableData[$key]['values']
-                            ) ? array_filter(
-                                $configurableData[$key]['values']
-                            ) : array()
+                            isset($configurableData[$key]['values'])
+                            ? array_filter($configurableData[$key]['values'])
+                            : array()
                         );
                     }
                 }
diff --git a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config/Matrix.php b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config/Matrix.php
index 74bb63b1fa1c651d50805d03f5cc99c6b78f5013..bcf30c8e1b6443d030e00c23c6bd9e1a415757e6 100644
--- a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config/Matrix.php
+++ b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config/Matrix.php
@@ -29,6 +29,9 @@ namespace Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super\Con
 
 use Magento\Catalog\Model\Product;
 
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
 class Matrix extends \Magento\Backend\Block\Template
 {
     /**
@@ -63,6 +66,11 @@ class Matrix extends \Magento\Backend\Block\Template
      */
     protected $stockItemService;
 
+    /**
+     * @var \Magento\ConfigurableProduct\Model\Product\Type\VariationMatrix
+     */
+    protected $variationMatrix;
+
     /**
      * @param \Magento\Backend\Block\Template\Context $context
      * @param \Magento\ConfigurableProduct\Model\Product\Type\Configurable $configurableType
@@ -71,6 +79,7 @@ class Matrix extends \Magento\Backend\Block\Template
      * @param \Magento\Framework\Registry $coreRegistry
      * @param \Magento\Framework\Locale\CurrencyInterface $localeCurrency
      * @param \Magento\CatalogInventory\Service\V1\StockItemServiceInterface $stockItemService
+     * @param \Magento\ConfigurableProduct\Model\Product\Type\VariationMatrix $variationMatrix
      * @param array $data
      */
     public function __construct(
@@ -81,8 +90,10 @@ class Matrix extends \Magento\Backend\Block\Template
         \Magento\Framework\Registry $coreRegistry,
         \Magento\Framework\Locale\CurrencyInterface $localeCurrency,
         \Magento\CatalogInventory\Service\V1\StockItemServiceInterface $stockItemService,
+        \Magento\ConfigurableProduct\Model\Product\Type\VariationMatrix $variationMatrix,
         array $data = array()
     ) {
+        parent::__construct($context, $data);
         $this->_configurableType = $configurableType;
         $this->_productFactory = $productFactory;
         $this->_config = $config;
@@ -90,6 +101,7 @@ class Matrix extends \Magento\Backend\Block\Template
         $this->_localeCurrency = $localeCurrency;
         $this->stockItemService = $stockItemService;
         parent::__construct($context, $data);
+        $this->variationMatrix = $variationMatrix;
     }
 
     /**
@@ -121,60 +133,10 @@ class Matrix extends \Magento\Backend\Block\Template
      * Retrieve all possible attribute values combinations
      *
      * @return array
-     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      */
     public function getVariations()
     {
-        $variationalAttributes = array();
-        $usedProductAttributes = $this->getAttributes();
-        foreach ($usedProductAttributes as $attribute) {
-            $options = array();
-            foreach ($attribute['options'] as $valueInfo) {
-                foreach ($attribute['values'] as $priceData) {
-                    if ($priceData['value_index'] == $valueInfo['value'] && (!isset(
-                        $priceData['include']
-                    ) || $priceData['include'])
-                    ) {
-                        $valueInfo['price'] = $priceData;
-                        $options[] = $valueInfo;
-                    }
-                }
-            }
-            /** @var $attribute \Magento\Catalog\Model\Resource\Eav\Attribute */
-            $variationalAttributes[] = array('id' => $attribute['attribute_id'], 'values' => $options);
-        }
-
-        $attributesCount = count($variationalAttributes);
-        if ($attributesCount === 0) {
-            return array();
-        }
-
-        $variations = array();
-        $currentVariation = array_fill(0, $attributesCount, 0);
-        $variationalAttributes = array_reverse($variationalAttributes);
-        $lastAttribute = $attributesCount - 1;
-        do {
-            for ($attributeIndex = 0; $attributeIndex < $attributesCount - 1; ++$attributeIndex) {
-                if ($currentVariation[$attributeIndex] >= count($variationalAttributes[$attributeIndex]['values'])) {
-                    $currentVariation[$attributeIndex] = 0;
-                    ++$currentVariation[$attributeIndex + 1];
-                }
-            }
-            if ($currentVariation[$lastAttribute] >= count($variationalAttributes[$lastAttribute]['values'])) {
-                break;
-            }
-
-            $filledVariation = array();
-            for ($attributeIndex = $attributesCount; $attributeIndex--;) {
-                $currentAttribute = $variationalAttributes[$attributeIndex];
-                $currentVariationValue = $currentVariation[$attributeIndex];
-                $filledVariation[$currentAttribute['id']] = $currentAttribute['values'][$currentVariationValue];
-            }
-
-            $variations[] = $filledVariation;
-            $currentVariation[0]++;
-        } while (1);
-        return $variations;
+        return $this->variationMatrix->getVariations($this->getAttributes());
     }
 
     /**
@@ -200,15 +162,14 @@ class Matrix extends \Magento\Backend\Block\Template
             $productData = (array)$this->getRequest()->getParam('product');
             if (isset($productData['configurable_attributes_data'])) {
                 $configurableData = $productData['configurable_attributes_data'];
-                foreach ($attributes as $key => &$attribute) {
+                foreach ($attributes as $key => $attribute) {
                     if (isset($configurableData[$key])) {
-                        $attribute['values'] = array_merge(
+                        $attributes[$key] = array_replace_recursive($attribute, $configurableData[$key]);
+                        $attributes[$key]['values'] = array_merge(
                             isset($attribute['values']) ? $attribute['values'] : array(),
-                            isset(
-                                $configurableData[$key]['values']
-                            ) ? array_filter(
-                                $configurableData[$key]['values']
-                            ) : array()
+                            isset($configurableData[$key]['values'])
+                            ? array_filter($configurableData[$key]['values'])
+                            : array()
                         );
                     }
                 }
diff --git a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config/Simple.php b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config/Simple.php
deleted file mode 100644
index 38d234e96bac7d79ab68b38dcee63ff5c7bfa0be..0000000000000000000000000000000000000000
--- a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config/Simple.php
+++ /dev/null
@@ -1,250 +0,0 @@
-<?php
-/**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
- */
-
-/**
- * Quick simple product creation
- */
-namespace Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super\Config;
-
-use Magento\Catalog\Model\Product;
-use Magento\Catalog\Model\ProductFactory;
-
-class Simple extends \Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Attributes
-{
-    /**
-     * Link to currently editing product
-     *
-     * @var Product
-     */
-    protected $_product = null;
-
-    /**
-     * @var ProductFactory
-     */
-    protected $_productFactory;
-
-    /**
-     * @param \Magento\Backend\Block\Template\Context $context
-     * @param \Magento\Framework\Registry $registry
-     * @param \Magento\Framework\Data\FormFactory $formFactory
-     * @param \Magento\Cms\Model\Wysiwyg\Config $wysiwygConfig
-     * @param \Magento\Catalog\Helper\Data $catalogData
-     * @param ProductFactory $productFactory
-     * @param array $data
-     */
-    public function __construct(
-        \Magento\Backend\Block\Template\Context $context,
-        \Magento\Framework\Registry $registry,
-        \Magento\Framework\Data\FormFactory $formFactory,
-        \Magento\Cms\Model\Wysiwyg\Config $wysiwygConfig,
-        \Magento\Catalog\Helper\Data $catalogData,
-        ProductFactory $productFactory,
-        array $data = array()
-    ) {
-        $this->_productFactory = $productFactory;
-        parent::__construct($context, $registry, $formFactory, $wysiwygConfig, $catalogData, $data);
-    }
-
-    /**
-     * Prepare form
-     *
-     * @return null|void
-     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
-     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
-     */
-    protected function _prepareForm()
-    {
-        /** @var \Magento\Framework\Data\Form $form */
-        $form = $this->_formFactory->create();
-
-        $form->setFieldNameSuffix('simple_product');
-        $form->setDataObject($this->getProduct());
-
-        $fieldset = $form->addFieldset('simple_product', array('legend' => __('Quick simple product creation')));
-        $this->_addElementTypes($fieldset);
-        $attributesConfig = array(
-            'autogenerate' => array('name', 'sku'),
-            'additional' => array('name', 'sku', 'visibility', 'status')
-        );
-
-        $availableTypes = array('text', 'select', 'multiselect', 'textarea', 'price', 'weight');
-
-        $attributes = $this->_productFactory->create()->setTypeId(
-            \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE
-        )->setAttributeSetId(
-            $this->getProduct()->getAttributeSetId()
-        )->getAttributes();
-
-        /* Standard attributes */
-        foreach ($attributes as $attribute) {
-            if (($attribute->getIsRequired() && $attribute->getApplyTo()
-                    // If not applied to configurable
-                    && !in_array(
-                        \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE,
-                        $attribute->getApplyTo()
-                    )
-                    // If not used in configurable
-                    && !in_array(
-                        $attribute->getId(),
-                        $this->getProduct()->getTypeInstance()->getUsedProductAttributeIds($this->getProduct())
-                    )
-                )
-                // Or in additional
-                || in_array($attribute->getAttributeCode(), $attributesConfig['additional'])
-            ) {
-                $inputType = $attribute->getFrontend()->getInputType();
-                if (!in_array($inputType, $availableTypes)) {
-                    continue;
-                }
-                $attributeCode = $attribute->getAttributeCode();
-                $attribute->setAttributeCode('simple_product_' . $attributeCode);
-                $element = $fieldset->addField(
-                    'simple_product_' . $attributeCode,
-                    $inputType,
-                    array(
-                        'label' => $attribute->getFrontend()->getLabel(),
-                        'name' => $attributeCode,
-                        'required' => $attribute->getIsRequired()
-                    )
-                )->setEntityAttribute(
-                    $attribute
-                );
-
-                if (in_array($attributeCode, $attributesConfig['autogenerate'])) {
-                    $element->setDisabled('true');
-                    $element->setValue($this->getProduct()->getData($attributeCode));
-                    $element->setAfterElementHtml(
-                        '<input type="checkbox" id="simple_product_' .
-                        $attributeCode .
-                        '_autogenerate" ' .
-                        'name="simple_product[' .
-                        $attributeCode .
-                        '_autogenerate]" value="1" ' .
-                        'onclick="toggleValueElements(this, this.parentNode)" checked="checked" /> ' .
-                        '<label for="simple_product_' .
-                        $attributeCode .
-                        '_autogenerate" >' .
-                        __(
-                            'Autogenerate'
-                        ) . '</label>'
-                    );
-                }
-
-
-                if ($inputType == 'select' || $inputType == 'multiselect') {
-                    $element->setValues($attribute->getFrontend()->getSelectOptions());
-                }
-            }
-        }
-
-        /* Configurable attributes */
-        $usedAttributes = $this->getProduct()->getTypeInstance()->getUsedProductAttributes($this->getProduct());
-        foreach ($usedAttributes as $attribute) {
-            $attributeCode = $attribute->getAttributeCode();
-            $fieldset->addField(
-                'simple_product_' . $attributeCode,
-                'select',
-                array(
-                    'label' => $attribute->getFrontend()->getLabel(),
-                    'name' => $attributeCode,
-                    'values' => $attribute->getSource()->getAllOptions(true, true),
-                    'required' => true,
-                    'class' => 'validate-configurable',
-                    'onchange' => 'superProduct.showPricing(this, \'' . $attributeCode . '\')'
-                )
-            );
-
-            $fieldset->addField(
-                'simple_product_' . $attributeCode . '_pricing_value',
-                'hidden',
-                array('name' => 'pricing[' . $attributeCode . '][value]')
-            );
-
-            $fieldset->addField(
-                'simple_product_' . $attributeCode . '_pricing_type',
-                'hidden',
-                array('name' => 'pricing[' . $attributeCode . '][is_percent]')
-            );
-        }
-
-        /* Inventory Data */
-        $fieldset->addField(
-            'simple_product_inventory_qty',
-            'text',
-            array(
-                'label' => __('Qty'),
-                'name' => 'stock_data[qty]',
-                'class' => 'validate-number',
-                'required' => true,
-                'value' => 0
-            )
-        );
-
-        $fieldset->addField(
-            'simple_product_inventory_is_in_stock',
-            'select',
-            array(
-                'label' => __('Stock Availability'),
-                'name' => 'stock_data[is_in_stock]',
-                'values' => array(
-                    array('value' => 1, 'label' => __('In Stock')),
-                    array('value' => 0, 'label' => __('Out of Stock'))
-                ),
-                'value' => 1
-            )
-        );
-
-        $stockHiddenFields = array(
-            'use_config_min_qty' => 1,
-            'use_config_min_sale_qty' => 1,
-            'use_config_max_sale_qty' => 1,
-            'use_config_backorders' => 1,
-            'use_config_notify_stock_qty' => 1,
-            'is_qty_decimal' => 0
-        );
-
-        foreach ($stockHiddenFields as $fieldName => $fieldValue) {
-            $fieldset->addField(
-                'simple_product_inventory_' . $fieldName,
-                'hidden',
-                array('name' => 'stock_data[' . $fieldName . ']', 'value' => $fieldValue)
-            );
-        }
-
-        $this->setForm($form);
-    }
-
-    /**
-     * Retrieve currently edited product object
-     *
-     * @return Product
-     */
-    public function getProduct()
-    {
-        if (!$this->_product) {
-            $this->_product = $this->_coreRegistry->registry('current_product');
-        }
-        return $this->_product;
-    }
-}
diff --git a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Builder/Plugin.php b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Builder/Plugin.php
index 0a86b955948898a8e8b6575636176c2f51199b3a..2f8ea42594c219e5e2aae3673f703545ee53974b 100644
--- a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Builder/Plugin.php
+++ b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Builder/Plugin.php
@@ -85,16 +85,10 @@ class Plugin
             }
         }
 
-        if ($request->getParam(
-            'popup'
-        ) && $request->getParam(
-            'product'
-        ) && !is_array(
-            $request->getParam('product')
-        ) && $request->getParam(
-            'id',
-            false
-        ) === false
+        if ($request->getParam('popup')
+            && $request->getParam('product')
+            && !is_array($request->getParam('product'))
+            && $request->getParam('id', false) === false
         ) {
             $configProduct = $this->productFactory->create();
             $configProduct->setStoreId(0)->load($request->getParam('product'))->setTypeId($request->getParam('type'));
diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php
index 62c0296a03e3b244a5e74cd08fbac3def800899b..040930fe74861d9a85b8d1f39104c61d16dc710d 100644
--- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php
+++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php
@@ -359,7 +359,7 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
      * Retrieve configurable attributes data
      *
      * @param  \Magento\Catalog\Model\Product $product
-     * @return array
+     * @return \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute[]
      */
     public function getConfigurableAttributes($product)
     {
@@ -455,11 +455,9 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
             }
 
             $usedProducts = array();
-            $collection = $this->getUsedProductCollection(
-                $product
-            )->addAttributeToSelect(
-                '*'
-            )->addFilterByRequiredOptions();
+            $collection = $this->getUsedProductCollection($product)->addAttributeToSelect('*')
+                ->addFilterByRequiredOptions()
+                ->setStoreId($product->getStoreId());
 
             if (is_array($requiredAttributeIds)) {
                 foreach ($requiredAttributeIds as $attributeId) {
diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Plugin.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Plugin.php
index 3b3ae2f8e0ffbc49687d800b4b106b03c9225533..648a6f3b09de5983a18690e5adf95a843e63e3a7 100644
--- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Plugin.php
+++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Plugin.php
@@ -42,7 +42,7 @@ class Plugin
     }
 
     /**
-     * Remove grouped product from list of visible product types
+     * Remove configurable product type from list of visible product types
      *
      * @param \Magento\Catalog\Model\Product\Type $subject
      * @param array $result
diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/VariationMatrix.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/VariationMatrix.php
new file mode 100644
index 0000000000000000000000000000000000000000..18f93795bf5f281be11d7ea03e9f3d53887d7a11
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/VariationMatrix.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\ConfigurableProduct\Model\Product\Type;
+
+class VariationMatrix
+{
+    /**
+     * Generate matrix of variation
+     *
+     * @param array $usedProductAttributes
+     * @return array
+     */
+    public function getVariations($usedProductAttributes)
+    {
+        $variationalAttributes = $this->combineVariationalAttributes($usedProductAttributes);
+
+        $attributesCount = count($variationalAttributes);
+        if ($attributesCount === 0) {
+            return [];
+        }
+
+        $variations = [];
+        $currentVariation = array_fill(0, $attributesCount, 0);
+        $variationalAttributes = array_reverse($variationalAttributes);
+        $lastAttribute = $attributesCount - 1;
+        do {
+            $this->incrementVariationalIndex($attributesCount, $variationalAttributes, $currentVariation);
+            if ($currentVariation[$lastAttribute] >= count($variationalAttributes[$lastAttribute]['values'])) {
+                break;
+            }
+
+            $filledVariation = [];
+            for ($attributeIndex = $attributesCount; $attributeIndex--;) {
+                $currentAttribute = $variationalAttributes[$attributeIndex];
+                $currentVariationValue = $currentVariation[$attributeIndex];
+                $filledVariation[$currentAttribute['id']] = $currentAttribute['values'][$currentVariationValue];
+            }
+
+            $variations[] = $filledVariation;
+            $currentVariation[0]++;
+        } while (true);
+
+        return $variations;
+    }
+
+    /**
+     * Combine variational attributes
+     *
+     * @param array $usedProductAttributes
+     * @return array
+     */
+    private function combineVariationalAttributes($usedProductAttributes)
+    {
+        $variationalAttributes = [];
+        foreach ($usedProductAttributes as $attribute) {
+            $options = array();
+            foreach ($attribute['options'] as $valueInfo) {
+                foreach ($attribute['values'] as $priceData) {
+                    if ($priceData['value_index'] == $valueInfo['value']
+                        && (!isset($priceData['include']) || $priceData['include'])
+                    ) {
+                        $valueInfo['price'] = $priceData;
+                        $options[] = $valueInfo;
+                    }
+                }
+            }
+            $variationalAttributes[] = array('id' => $attribute['attribute_id'], 'values' => $options);
+        }
+        return $variationalAttributes;
+    }
+
+    /**
+     * Increment index in variation with shift if overflow
+     *
+     * @param int $attributesCount
+     * @param array $variationalAttributes
+     * @param array $currentVariation
+     * @return void
+     */
+    private function incrementVariationalIndex($attributesCount, $variationalAttributes, &$currentVariation)
+    {
+        for ($attributeIndex = 0; $attributeIndex < $attributesCount - 1; ++$attributeIndex) {
+            if ($currentVariation[$attributeIndex] >= count($variationalAttributes[$attributeIndex]['values'])) {
+                $currentVariation[$attributeIndex] = 0;
+                ++$currentVariation[$attributeIndex + 1];
+            }
+        }
+    }
+}
diff --git a/app/code/Magento/ConfigurableProduct/Service/V1/Data/ConfigurableAttribute.php b/app/code/Magento/ConfigurableProduct/Service/V1/Data/ConfigurableAttribute.php
new file mode 100644
index 0000000000000000000000000000000000000000..99e92729f394e705900da888d17d7aa82561537a
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Service/V1/Data/ConfigurableAttribute.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\ConfigurableProduct\Service\V1\Data;
+
+class ConfigurableAttribute extends \Magento\Framework\Service\Data\AbstractObject
+{
+    const ID = 'id';
+    const LABEL = 'label';
+    const USE_DEFAULT = 'use_default';
+    const POSITION = 'position';
+    const VALUES = 'values';
+    const ATTRIBUTE_ID = 'attribute_id';
+
+    /**
+     * @return int|null
+     */
+    public function getId()
+    {
+        return $this->_get(self::ID);
+    }
+
+    /**
+     * @return string
+     */
+    public function getAttributeId()
+    {
+        return $this->_get(self::ATTRIBUTE_ID);
+    }
+
+    /**
+     * @return string|null
+     */
+    public function getLabel()
+    {
+        return $this->_get(self::LABEL);
+    }
+
+    /**
+     * @return bool|null
+     */
+    public function isUseDefault()
+    {
+        return $this->_get(self::USE_DEFAULT);
+    }
+
+    /**
+     * @return \Magento\ConfigurableProduct\Service\V1\Data\ConfigurableAttribute\Value[]
+     */
+    public function getValues()
+    {
+        return $this->_get(self::VALUES);
+    }
+}
diff --git a/app/code/Magento/ConfigurableProduct/Service/V1/Data/ConfigurableAttribute/Value.php b/app/code/Magento/ConfigurableProduct/Service/V1/Data/ConfigurableAttribute/Value.php
new file mode 100644
index 0000000000000000000000000000000000000000..6b88e10b4ac8b6f335ced46690ecc0e14087c1d8
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Service/V1/Data/ConfigurableAttribute/Value.php
@@ -0,0 +1,55 @@
+<?php
+namespace Magento\ConfigurableProduct\Service\V1\Data\ConfigurableAttribute;
+
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+class Value extends \Magento\Framework\Service\Data\AbstractObject
+{
+    const INDEX = 'value_index';
+    const PRICE = 'pricing_value';
+    const PRICE_IS_PERCENT = 'is_percent';
+
+    /**
+     * @return float|null
+     */
+    public function getPrice()
+    {
+        return $this->_get(self::PRICE);
+    }
+
+    /**
+     * @return int|null
+     */
+    public function getPriceIsPercent()
+    {
+        return $this->_get(self::PRICE_IS_PERCENT);
+    }
+
+    /**
+     * @return int
+     */
+    public function getIndex()
+    {
+        return $this->_get(self::INDEX);
+    }
+}
diff --git a/app/code/Magento/ConfigurableProduct/Service/V1/Data/ConfigurableAttribute/ValueBuilder.php b/app/code/Magento/ConfigurableProduct/Service/V1/Data/ConfigurableAttribute/ValueBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..511e1c33b15f7296a58870a5e4e0afc10ab8237f
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Service/V1/Data/ConfigurableAttribute/ValueBuilder.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\ConfigurableProduct\Service\V1\Data\ConfigurableAttribute;
+
+use Magento\Framework\Service\Data\AbstractObjectBuilder;
+
+class ValueBuilder extends AbstractObjectBuilder
+{
+    /**
+     * @param float $value 
+     * @return self 
+     */
+    public function setPrice($value)
+    {
+        return $this->_set(Value::PRICE, $value);
+    }
+
+    /**
+     * @param int $value 
+     * @return self 
+     */
+    public function setPriceIsPercent($value)
+    {
+        return $this->_set(Value::PRICE_IS_PERCENT, $value);
+    }
+
+    /**
+     * @param int $value
+     * @return self
+     */
+    public function setIndex($value)
+    {
+        return $this->_set(Value::INDEX, $value);
+    }
+}
diff --git a/app/code/Magento/ConfigurableProduct/Service/V1/Data/ConfigurableAttributeBuilder.php b/app/code/Magento/ConfigurableProduct/Service/V1/Data/ConfigurableAttributeBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..a50a266156f4f1a7bd39c0ca8b30f1a9c7d107ed
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Service/V1/Data/ConfigurableAttributeBuilder.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\ConfigurableProduct\Service\V1\Data;
+
+class ConfigurableAttributeBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
+{
+    /**
+     * @param int $value 
+     * @return self 
+     */
+    public function setId($value)
+    {
+        return $this->_set(ConfigurableAttribute::ID, $value);
+    }
+
+    /**
+     * @param string $value
+     * @return self 
+     */
+    public function setAttributeId($value)
+    {
+        return $this->_set(ConfigurableAttribute::ATTRIBUTE_ID, $value);
+    }
+
+    /**
+     * @param string $value 
+     * @return self 
+     */
+    public function setLabel($value)
+    {
+        return $this->_set(ConfigurableAttribute::LABEL, $value);
+    }
+
+    /**
+     * @param bool $value 
+     * @return self 
+     */
+    public function useDefault($value)
+    {
+        return $this->_set(ConfigurableAttribute::USE_DEFAULT, $value);
+    }
+
+    /**
+     * @param \Magento\ConfigurableProduct\Service\V1\Data\ConfigurableAttribute\Value[] $value 
+     * @return self 
+     */
+    public function setValues($value)
+    {
+        return $this->_set(ConfigurableAttribute::VALUES, $value);
+    }
+}
diff --git a/app/code/Magento/ConfigurableProduct/Service/V1/Product/Link/ReadService.php b/app/code/Magento/ConfigurableProduct/Service/V1/Product/Link/ReadService.php
new file mode 100644
index 0000000000000000000000000000000000000000..c1729e605fff2ad82127bf7b7dfca72796467408
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Service/V1/Product/Link/ReadService.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\ConfigurableProduct\Service\V1\Product\Link;
+
+use Magento\Catalog\Model\Product;
+use Magento\Catalog\Model\ProductRepository;
+use Magento\Catalog\Service\V1\Data\Converter;
+
+class ReadService implements ReadServiceInterface
+{
+    /**
+     * @var \Magento\Catalog\Model\ProductRepository
+     */
+    private $productRepository;
+
+    /**
+     * @var Converter
+     */
+    private $productConverter;
+
+    /**
+     * @param ProductRepository $productRepository
+     * @param Converter $productConverter
+     */
+    public function __construct(
+        ProductRepository $productRepository,
+        Converter $productConverter
+    ) {
+        $this->productRepository = $productRepository;
+        $this->productConverter = $productConverter;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getChildren($productId)
+    {
+        $product = $this->productRepository->get($productId);
+        if ($product->getTypeId() != \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE) {
+            return [];
+        }
+
+        $childrenList = [];
+
+        /** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable $productTypeInstance */
+        $productTypeInstance = $product->getTypeInstance();
+        $productTypeInstance->setStoreFilter(
+            $product->getStoreId(),
+            $product
+        );
+
+        foreach ($productTypeInstance->getUsedProducts($product) as $child) {
+            $childrenList[] = $this->productConverter->createProductDataFromModel($child);
+        }
+
+        return $childrenList;
+    }
+}
diff --git a/app/code/Magento/ConfigurableProduct/Service/V1/Product/Link/ReadServiceInterface.php b/app/code/Magento/ConfigurableProduct/Service/V1/Product/Link/ReadServiceInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..fbed7b387fb580c7c905553893a0ce5ce53e9a52
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Service/V1/Product/Link/ReadServiceInterface.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\ConfigurableProduct\Service\V1\Product\Link;
+
+
+interface ReadServiceInterface
+{
+    /**
+     * Get all children for Bundle product
+     *
+     * @param string $productId
+     * @return \Magento\Catalog\Service\V1\Data\Product[]
+     */
+    public function getChildren($productId);
+}
diff --git a/app/code/Magento/ConfigurableProduct/Service/V1/Product/Link/WriteService.php b/app/code/Magento/ConfigurableProduct/Service/V1/Product/Link/WriteService.php
new file mode 100644
index 0000000000000000000000000000000000000000..a013337833146db23303c66279316ddcfbc32bad
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Service/V1/Product/Link/WriteService.php
@@ -0,0 +1,107 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\ConfigurableProduct\Service\V1\Product\Link;
+
+use \Magento\Catalog\Model\ProductRepository;
+use \Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable;
+use Magento\Framework\Exception\StateException;
+use Magento\Catalog\Model\Product;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Webapi\Exception;
+
+class WriteService implements WriteServiceInterface
+{
+    /**
+     * @var \Magento\Catalog\Model\ProductRepository
+     */
+    protected $productRepository;
+
+    /**
+     * @var Configurable
+     */
+    protected $configurableType;
+
+    /**
+     * @param ProductRepository $productRepository
+     * @param Configurable $configurableType
+     * @internal param ConfigurableFactory $typeConfigurableFactory
+     */
+    public function __construct(
+        ProductRepository $productRepository,
+        Configurable $configurableType
+    ) {
+        $this->productRepository = $productRepository;
+        $this->configurableType = $configurableType;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function addChild($productSku, $childSku)
+    {
+        $product = $this->productRepository->get($productSku);
+        $child = $this->productRepository->get($childSku);
+
+        $childrenIds = array_values($this->configurableType->getChildrenIds($product->getId())[0]);
+        if (in_array($child->getId(), $childrenIds)) {
+            throw new StateException('Product has been already attached');
+        }
+
+        $childrenIds[] = $child->getId();
+        $product->setAssociatedProductIds($childrenIds);
+        $product->save();
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function removeChild($productSku, $childSku)
+    {
+        $product = $this->productRepository->get($productSku);
+
+        if ($product->getTypeId() != \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE) {
+            throw new Exception(
+                sprintf('Product with specified sku: %s is not a configurable product', $productSku),
+                Exception::HTTP_FORBIDDEN
+            );
+        }
+
+        $options = $product->getTypeInstance()->getUsedProducts($product);
+        $ids = array();
+        foreach ($options as $option) {
+            if ($option->getSku() == $childSku) {
+                continue;
+            }
+            $ids[] = $option->getId();
+        }
+        if (count($options) == count($ids)) {
+            throw new NoSuchEntityException('Requested option doesn\'t exist');
+        }
+        $product->addData(['associated_product_ids' => $ids]);
+        $product->save();
+
+        return true;
+    }
+}
diff --git a/app/code/Magento/ConfigurableProduct/Service/V1/Product/Link/WriteServiceInterface.php b/app/code/Magento/ConfigurableProduct/Service/V1/Product/Link/WriteServiceInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..edbb1b0fdff8a2ccf5f99c86fad8b394ee8fb051
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Service/V1/Product/Link/WriteServiceInterface.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\ConfigurableProduct\Service\V1\Product\Link;
+
+interface WriteServiceInterface
+{
+    /**
+     * @param  string $productSku
+     * @param  string $childSku
+     * @return bool
+     */
+    public function addChild($productSku, $childSku);
+
+    /**
+     * Remove configurable product option
+     *
+     * @param string $productSku
+     * @param string $childSku
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     * @throws \Magento\Webapi\Exception
+     * @return bool
+     */
+    public function removeChild($productSku, $childSku);
+}
diff --git a/app/code/Magento/ConfigurableProduct/Service/V1/ReadService.php b/app/code/Magento/ConfigurableProduct/Service/V1/ReadService.php
new file mode 100644
index 0000000000000000000000000000000000000000..d79190379d38b2a7a4bd79fa89cd80ac2db69679
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Service/V1/ReadService.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\ConfigurableProduct\Service\V1;
+
+use Magento\Catalog\Service\V1\Data\Product;
+use Magento\Catalog\Service\V1\Data\ProductBuilder;
+use Magento\Catalog\Service\V1\Product\Attribute;
+use Magento\ConfigurableProduct\Model\Product\Type\VariationMatrix;
+
+class ReadService implements ReadServiceInterface
+{
+    /**
+     * @var VariationMatrix
+     */
+    private $variationMatrix;
+
+    /**
+     * @var ProductBuilder
+     */
+    private $productBuilder;
+
+    /**
+     * @var Attribute\ReadServiceInterface
+     */
+    private $attributeReadService;
+
+    /**
+     * @param Attribute\ReadServiceInterface $attributeReadService
+     * @param ProductBuilder $productBuilder
+     * @param VariationMatrix $variationMatrix
+     */
+    public function __construct(
+        Attribute\ReadServiceInterface $attributeReadService,
+        ProductBuilder $productBuilder,
+        VariationMatrix $variationMatrix
+    ) {
+        $this->variationMatrix = $variationMatrix;
+        $this->productBuilder = $productBuilder;
+        $this->attributeReadService = $attributeReadService;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function generateVariation(Product $product, $configurableAttributes)
+    {
+        $attributes = $this->getAttributesForMatrix($configurableAttributes);
+        $variations = $this->variationMatrix->getVariations($attributes);
+        $products = $this->populateProductVariation($product, $variations, $attributes);
+        return $products;
+    }
+
+    /**
+     * Prepare attribute info for variation matrix generation
+     *
+     * @param \Magento\ConfigurableProduct\Service\V1\Data\ConfigurableAttribute[] $configurableAttributes
+     * @return array
+     */
+    private function getAttributesForMatrix($configurableAttributes)
+    {
+        $attributes = [];
+        foreach ($configurableAttributes as $configurableAttribute) {
+            $configurable = $configurableAttribute->__toArray();
+            $attribute = $this->attributeReadService->info($configurableAttribute->getAttributeId());
+            $configurable['options'] = $attribute->__toArray()['options'];
+            $configurable['attribute_code'] = $attribute->getAttributeCode();
+            $attributes[$configurableAttribute->getAttributeId()] = $configurable;
+        }
+        return $attributes;
+    }
+
+    /**
+     * Populate product with variation of attributes
+     *
+     * @param Product $product
+     * @param array $variations
+     * @param array $attributes
+     * @return array
+     */
+    private function populateProductVariation(Product $product, $variations, $attributes)
+    {
+        $products = [];
+        foreach ($variations as $attributeId => $variation) {
+            $price = $product->getPrice();
+            $this->productBuilder->populate($product);
+            $suffix = '';
+            foreach ($variation as $attributeId => $valueInfo) {
+                $suffix .= '-' . $valueInfo['value'];
+                $this->productBuilder->setCustomAttribute(
+                    $attributes[$attributeId]['attribute_code'],
+                    $valueInfo['value']
+                );
+                $priceInfo = $valueInfo['price'];
+                $price += (!empty($priceInfo['is_percent']) ? $product->getPrice() / 100.0 : 1.0)
+                    * $priceInfo['pricing_value'];
+            }
+            $this->productBuilder->setPrice($price);
+            $this->productBuilder->setName($product->getName() . $suffix);
+            $this->productBuilder->setSku($product->getSku() . $suffix);
+            $this->productBuilder->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE);
+            $products[] = $this->productBuilder->create();
+        }
+        return $products;
+    }
+}
diff --git a/app/code/Magento/ConfigurableProduct/Service/V1/ReadServiceInterface.php b/app/code/Magento/ConfigurableProduct/Service/V1/ReadServiceInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..49ac8f1ff90f143624ab5a3baf68a2a170ed60de
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Service/V1/ReadServiceInterface.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\ConfigurableProduct\Service\V1;
+
+interface ReadServiceInterface
+{
+    /**
+     * Generate variation based on same product
+     *
+     * @param \Magento\Catalog\Service\V1\Data\Product $product
+     * @param \Magento\ConfigurableProduct\Service\V1\Data\ConfigurableAttribute[] $configurableAttributes
+     * @return \Magento\Catalog\Service\V1\Data\Product[]
+     */
+    public function generateVariation(
+        \Magento\Catalog\Service\V1\Data\Product $product,
+        $configurableAttributes
+    );
+}
diff --git a/app/code/Magento/ConfigurableProduct/etc/di.xml b/app/code/Magento/ConfigurableProduct/etc/di.xml
index 35789f99cbee9806ca1d6eee5f9420def464a0a9..472fdd85bdc1eb857a6c76bd10c34545d5588c82 100644
--- a/app/code/Magento/ConfigurableProduct/etc/di.xml
+++ b/app/code/Magento/ConfigurableProduct/etc/di.xml
@@ -24,6 +24,9 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+    <preference for="Magento\ConfigurableProduct\Service\V1\Product\Link\ReadServiceInterface" type="Magento\ConfigurableProduct\Service\V1\Product\Link\ReadService" />
+    <preference for="Magento\ConfigurableProduct\Service\V1\Product\Link\WriteServiceInterface" type="Magento\ConfigurableProduct\Service\V1\Product\Link\WriteService" />
+    <preference for="Magento\ConfigurableProduct\Service\V1\ReadServiceInterface" type="Magento\ConfigurableProduct\Service\V1\ReadService" />
     <type name="Magento\CatalogInventory\Model\Quote\Item\QuantityValidator\Initializer\Option">
         <plugin name="configurable_product" type="Magento\ConfigurableProduct\Model\Quote\Item\QuantityValidator\Initializer\Option\Plugin\ConfigurableProduct" sortOrder="50" />
     </type>
diff --git a/app/code/Magento/ConfigurableProduct/etc/module.xml b/app/code/Magento/ConfigurableProduct/etc/module.xml
index 7601658945adb91731dd8a60c247e99213dc93e4..71ed9ee44314bda417fd1aa6420b9e5da6a98b26 100644
--- a/app/code/Magento/ConfigurableProduct/etc/module.xml
+++ b/app/code/Magento/ConfigurableProduct/etc/module.xml
@@ -42,12 +42,12 @@
             <module name="Magento_Theme" />
             <module name="Magento_Backend" />
             <module name="Magento_Eav" />
-            <module name="Magento_Cms" />
             <module name="Magento_Customer" />
             <module name="Magento_CatalogRule" />
             <module name="Magento_Directory" />
             <module name="Magento_Weee" />
             <module name="Magento_RequireJs" />
+            <module name="Magento_Webapi"/>
         </depends>
     </module>
 </config>
diff --git a/app/code/Magento/ConfigurableProduct/etc/webapi.xml b/app/code/Magento/ConfigurableProduct/etc/webapi.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fd11c2f6b29fa57723920d2784465e14c0596480
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/etc/webapi.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:noNamespaceSchemaLocation="../../../../../app/code/Magento/Webapi/etc/webapi.xsd">
+    <route url="/V1/configurable-products/:productId/children" method="GET">
+        <service class="Magento\ConfigurableProduct\Service\V1\Product\Link\ReadServiceInterface" method="getChildren"/>
+        <resources>
+            <resource ref="Magento_Catalog::products"/>
+        </resources>
+    </route>
+    <route url="/V1/configurable-products/:productSku/child/:childSku" method="DELETE">
+        <service class="Magento\ConfigurableProduct\Service\V1\Product\Link\WriteServiceInterface" method="removeChild"/>
+        <resources>
+            <resource ref="Magento_Catalog::products"/>
+        </resources>
+    </route>
+    <route url="/V1/configurable-products/variation" method="PUT">
+        <service class="Magento\ConfigurableProduct\Service\V1\ReadServiceInterface" method="generateVariation" />
+        <resources>
+            <resource ref="Magento_Catalog::products" />
+        </resources>
+    </route>
+    <route url="/V1/configurable-products/:productSku/child" method="POST">
+        <service class="Magento\ConfigurableProduct\Service\V1\Product\Link\WriteServiceInterface" method="addChild" />
+        <resources>
+            <resource ref="Magento_Catalog::products" />
+        </resources>
+    </route>
+</routes>
diff --git a/app/code/Magento/Core/Model/View/Design.php b/app/code/Magento/Core/Model/View/Design.php
index 8bfb62a8be3be845b74a37f5e50bf472894b5a7e..7d7d7bf61ca6210d5917fe82c4379169999bea3e 100644
--- a/app/code/Magento/Core/Model/View/Design.php
+++ b/app/code/Magento/Core/Model/View/Design.php
@@ -22,11 +22,11 @@
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
 
+namespace Magento\Core\Model\View;
+
 /**
  * Keeps design settings for current request
  */
-namespace Magento\Core\Model\View;
-
 class Design implements \Magento\Framework\View\DesignInterface
 {
     /**
@@ -177,14 +177,18 @@ class Design implements \Magento\Framework\View\DesignInterface
         $store = isset($params['store']) ? $params['store'] : null;
 
         if ($this->_isThemePerStoveView($area)) {
-            $theme = $this->_storeManager->isSingleStoreMode() ? $this->_scopeConfig->getValue(
-                self::XML_PATH_THEME_ID,
-                \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT
-            ) : (string)$this->_scopeConfig->getValue(
-                self::XML_PATH_THEME_ID,
-                \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
-                $store
-            );
+            if ($this->_storeManager->isSingleStoreMode()) {
+                $theme = $this->_scopeConfig->getValue(
+                    self::XML_PATH_THEME_ID,
+                    \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT
+                );
+            } else {
+                $theme = (string) $this->_scopeConfig->getValue(
+                    self::XML_PATH_THEME_ID,
+                    \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+                    $store
+                );
+            }
         }
 
         if (!$theme && isset($this->_themes[$area])) {
diff --git a/app/code/Magento/Customer/Block/Adminhtml/Form/Element/Image.php b/app/code/Magento/Customer/Block/Adminhtml/Form/Element/Image.php
index 5381bdd33389f0e40e65dfcc1c429713331f3832..fbab79b2aac2c7487c94ff49ae62336ea400faba 100644
--- a/app/code/Magento/Customer/Block/Adminhtml/Form/Element/Image.php
+++ b/app/code/Magento/Customer/Block/Adminhtml/Form/Element/Image.php
@@ -90,12 +90,9 @@ class Image extends \Magento\Customer\Block\Adminhtml\Form\Element\File
      */
     protected function _getPreviewUrl()
     {
-        if (is_array($this->getValue())) {
-            return false;
-        }
         return $this->_adminhtmlData->getUrl(
             'customer/index/viewfile',
-            array('image' => $this->_escaper->urlEncode($this->getValue()))
+            array('image' => $this->_adminhtmlData->urlEncode($this->getValue()))
         );
     }
 }
diff --git a/app/code/Magento/Customer/view/frontend/templates/account/dashboard/address.phtml b/app/code/Magento/Customer/view/frontend/templates/account/dashboard/address.phtml
index 119de95d8f5de7ba0172b9dfd0ec27a1621639e5..b92be230b99e6c8f82cc84b2e84547e86622514c 100644
--- a/app/code/Magento/Customer/view/frontend/templates/account/dashboard/address.phtml
+++ b/app/code/Magento/Customer/view/frontend/templates/account/dashboard/address.phtml
@@ -24,29 +24,37 @@
 
 /** @var \Magento\Customer\Block\Account\Dashboard\Address $this */
 ?>
-<div class="block dashboard addresses">
-    <div class="title">
+<div class="block block-dashboard-addresses">
+    <div class="block-title">
         <strong><?php echo __('Address Book') ?></strong>
         <a class="action edit" href="<?php echo $this->getAddressBookUrl() ?>"><span><?php echo __('Manage Addresses') ?></span></a>
     </div>
-    <div class="content">
-        <div class="box address billing">
-            <strong class="subtitle">
+    <div class="block-content">
+        <div class="box box-address-billing">
+            <strong class="box-title">
                 <span><?php echo __('Default Billing Address') ?></span>
-                <a class="action edit" href="<?php echo $this->getPrimaryBillingAddressEditUrl() ?>" data-ui-id="default-billing-edit-link"><span><?php echo __('Edit Address') ?></span></a>
             </strong>
-            <address>
-                <?php echo $this->getPrimaryBillingAddressHtml() ?>
-            </address>
+            <div class="box-content">
+                <address>
+                    <?php echo $this->getPrimaryBillingAddressHtml() ?>
+                </address>
+            </div>
+            <div class="box-actions">
+                <a class="action edit" href="<?php echo $this->getPrimaryBillingAddressEditUrl() ?>" data-ui-id="default-billing-edit-link"><span><?php echo __('Edit Address') ?></span></a>
+            </div>
         </div>
-        <div class="box address shipping">
-            <strong class="subtitle">
+        <div class="box box-address-shipping">
+            <strong class="box-title">
                 <span><?php echo __('Default Shipping Address') ?></span>
-                <a class="action edit" href="<?php echo $this->getPrimaryShippingAddressEditUrl() ?>" data-ui-id="default-shipping-edit-link"><span><?php echo __('Edit Address') ?></span></a>
             </strong>
-            <address>
-                <?php echo $this->getPrimaryShippingAddressHtml() ?>
-            </address>
+            <div class="box-content">
+                <address>
+                    <?php echo $this->getPrimaryShippingAddressHtml() ?>
+                </address>
+            </div>
+            <div class="box-actions">
+                <a class="action edit" href="<?php echo $this->getPrimaryShippingAddressEditUrl() ?>" data-ui-id="default-shipping-edit-link"><span><?php echo __('Edit Address') ?></span></a>
+            </div>
         </div>
     </div>
 </div>
diff --git a/app/code/Magento/Customer/view/frontend/templates/account/dashboard/hello.phtml b/app/code/Magento/Customer/view/frontend/templates/account/dashboard/hello.phtml
index 26b5a5081c6809a6d34a4e9a81664dec65d2d95b..9ed5b2ffd2b7e843faab8c452178489376dca81f 100644
--- a/app/code/Magento/Customer/view/frontend/templates/account/dashboard/hello.phtml
+++ b/app/code/Magento/Customer/view/frontend/templates/account/dashboard/hello.phtml
@@ -24,9 +24,9 @@
 
 /** @var \Magento\Customer\Block\Account\Dashboard\Hello $this */
 ?>
-<div class="block dashboard welcome">
-    <div class="title"><strong><?php echo __('Hello, %1!', $this->escapeHtml($this->getCustomerName())) ?></strong></div>
-    <div class="content">
+<div class="block block-dashboard-welcome">
+    <div class="block-title"><strong><?php echo __('Hello, %1!', $this->escapeHtml($this->getCustomerName())) ?></strong></div>
+    <div class="block-content">
         <p><?php echo __('From your My Account Dashboard you have the ability to view a snapshot of your recent account activity and update your account information. Select a link below to view or edit information.') ?></p>
     </div>
 </div>
diff --git a/app/code/Magento/Customer/view/frontend/templates/account/dashboard/info.phtml b/app/code/Magento/Customer/view/frontend/templates/account/dashboard/info.phtml
index 49189b893d8ff95c104a6570a1ebdddcaba02246..4deeac8f86c0a318cf91532f4159e5c5063e2148 100644
--- a/app/code/Magento/Customer/view/frontend/templates/account/dashboard/info.phtml
+++ b/app/code/Magento/Customer/view/frontend/templates/account/dashboard/info.phtml
@@ -24,35 +24,47 @@
 
 /** @var \Magento\Customer\Block\Account\Dashboard\Info $this */
 ?>
-<div class="block dashboard info">
-    <div class="title"><strong><?php echo __('Account Information') ?></strong></div>
-    <div class="content">
-        <div class="box information">
-            <strong class="subtitle">
-                <?php echo __('Contact Information') ?>
-                <a class="action edit" href="<?php echo $this->getUrl('customer/account/edit') ?>"><span><?php echo __('Edit') ?></span></a>
+<div class="block block-dashboard-info">
+    <div class="block-title"><strong><?php echo __('Account Information') ?></strong></div>
+    <div class="block-content">
+        <div class="box box-information">
+            <strong class="box-title">
+                <span><?php echo __('Contact Information') ?></span>
             </strong>
-            <p>
-                <?php echo $this->escapeHtml($this->getName()) ?><br>
-                <?php echo $this->escapeHtml($this->getCustomer()->getEmail()) ?><br>
-                <a href="<?php echo $this->getChangePasswordUrl() ?>"><?php echo __('Change Password') ?></a>
-            </p>
+            <div class="box-content">
+                <p>
+                    <?php echo $this->escapeHtml($this->getName()) ?><br>
+                    <?php echo $this->escapeHtml($this->getCustomer()->getEmail()) ?><br>
+                </p>
+            </div>
+            <div class="box-actions">
+                <a class="action edit" href="<?php echo $this->getUrl('customer/account/edit') ?>">
+                    <span><?php echo __('Edit') ?></span>
+                </a>
+                <a href="<?php echo $this->getChangePasswordUrl() ?>" class="action change-password">
+                    <?php echo __('Change Password') ?>
+                </a>
+            </div>
         </div>
         <?php if( $this->isNewsletterEnabled() ): ?>
-            <div class="box newsletter">
-                <strong class="subtitle">
-                    <?php echo __('Newsletters') ?>
-                    <a class="action edit" href="<?php echo $this->getUrl('newsletter/manage') ?>"><span><?php echo __('Edit') ?></span></a>
+            <div class="box box-newsletter">
+                <strong class="box-title">
+                    <span><?php echo __('Newsletters') ?></span>
                 </strong>
-                <p>
-                    <?php if( $this->getIsSubscribed() ): ?>
-                        <?php echo __("You are currently subscribed to 'General Subscription'.") ?>
-                    <?php else: ?>
-                        <?php echo __('You are currently not subscribed to any newsletter.') ?>
-                    <?php endif; ?>
-                </p>
-                <?php /* Extensions placeholder */ ?>
-                <?php echo $this->getChildHtml('customer.account.dashboard.info.extra')?>
+                <div class="box-content">
+                    <p>
+                        <?php if( $this->getIsSubscribed() ): ?>
+                            <?php echo __("You are currently subscribed to 'General Subscription'.") ?>
+                        <?php else: ?>
+                            <?php echo __('You are currently not subscribed to any newsletter.') ?>
+                        <?php endif; ?>
+                    </p>
+                    <?php /* Extensions placeholder */ ?>
+                    <?php echo $this->getChildHtml('customer.account.dashboard.info.extra')?>
+                </div>
+                <div class="box-actions">
+                    <a class="action edit" href="<?php echo $this->getUrl('newsletter/manage') ?>"><span><?php echo __('Edit') ?></span></a>
+                </div>
             </div>
         <?php endif; ?>
     </div>
diff --git a/app/code/Magento/Customer/view/frontend/templates/account/navigation.phtml b/app/code/Magento/Customer/view/frontend/templates/account/navigation.phtml
index fbac1f6bf7d055fa554e9ccdb85d48b28c684091..33a10b372e627f2ebfeb7b0d8d119cbcf716d850 100644
--- a/app/code/Magento/Customer/view/frontend/templates/account/navigation.phtml
+++ b/app/code/Magento/Customer/view/frontend/templates/account/navigation.phtml
@@ -24,12 +24,12 @@
 /** @var $this \Magento\Framework\View\Element\Html\Links */
 ?>
 <?php /** @var $this \Magento\Customer\Block\Account\Navigation */ ?>
-<div class="block account nav">
+<div class="block account-nav">
     <div class="title">
         <strong><?php echo __('My Account'); ?></strong>
     </div>
     <div class="content">
-        <nav class="account nav">
+        <nav class="account-nav">
             <ul class="nav items">
                 <?php echo $this->getChildHtml();?>
             </ul>
diff --git a/app/code/Magento/Customer/view/frontend/templates/address/book.phtml b/app/code/Magento/Customer/view/frontend/templates/address/book.phtml
index f1b08dcae13b345b3035bb0efc4c30b8fcfdd901..b39c39eb4bed6638d73054103682024f64c46c36 100644
--- a/app/code/Magento/Customer/view/frontend/templates/address/book.phtml
+++ b/app/code/Magento/Customer/view/frontend/templates/address/book.phtml
@@ -28,52 +28,64 @@
  * @var $this \Magento\Customer\Block\Address\Book
  */
 ?>
-<div class="block addresses default">
-    <div class="title"><strong><?php echo __('Default Addresses') ?></strong></div>
-    <div class="content">
+<div class="block block-addresses-default">
+    <div class="block-title"><strong><?php echo __('Default Addresses') ?></strong></div>
+    <div class="block-content">
         <?php if($_pAddsses = $this->getDefaultBilling()): ?>
-            <div class="box address billing">
-                <strong class="subtitle">
+            <div class="box box-address-billing">
+                <strong class="box-title">
                     <span><?php echo __('Default Billing Address') ?></span>
+                </strong>
+                <div class="box-content">
+                    <address>
+                        <?php echo $this->getAddressHtml($this->getAddressById($_pAddsses)) ?>
+                    </address>
+                </div>
+                <div class="box-actions">
                     <a class="action edit" href="<?php echo $this->getAddressEditUrl($_pAddsses) ?>">
                         <span><?php echo __('Change Billing Address') ?></span>
                     </a>
-                </strong>
-                <address>
-                    <?php echo $this->getAddressHtml($this->getAddressById($_pAddsses)) ?>
-                </address>
+                </div>
             </div>
         <?php else: ?>
-            <div class="box address billing">
-                <strong class="subtitle"><span><?php echo __('Default Billing Address') ?></span></strong>
-                <p><?php echo __('You have no default billing address in your address book.') ?></p>
+            <div class="box box-address-billing">
+                <strong class="box-title"><span><?php echo __('Default Billing Address') ?></span></strong>
+                <div class="box-content">
+                    <p><?php echo __('You have no default billing address in your address book.') ?></p>
+                </div>
             </div>
         <?php endif ?>
 
         <?php if($_pAddsses = $this->getDefaultShipping()): ?>
-            <div class="box address shipping">
-                <strong class="subtitle">
+            <div class="box box-address-shipping">
+                <strong class="box-title">
                     <span><?php echo __('Default Shipping Address') ?></span>
+                </strong>
+                <div class="box-content">
+                    <address>
+                        <?php echo $this->getAddressHtml($this->getAddressById($_pAddsses)) ?>
+                    </address>
+                </div>
+                <div class="box-actions">
                     <a class="action edit" href="<?php echo $this->getAddressEditUrl($_pAddsses) ?>">
                         <span><?php echo __('Change Shipping Address') ?></span>
                     </a>
-                </strong>
-                <address>
-                    <?php echo $this->getAddressHtml($this->getAddressById($_pAddsses)) ?>
-                </address>
+                </div>
             </div>
         <?php else: ?>
-            <div class="box address shipping">
-                <strong class="subtitle"><span><?php echo __('Default Shipping Address') ?></span></strong>
-                <p><?php echo __('You have no default shipping address in your address book.') ?></p>
+            <div class="box box-address-shipping">
+                <strong class="box-title"><span><?php echo __('Default Shipping Address') ?></span></strong>
+                <div class="box-content">
+                    <p><?php echo __('You have no default shipping address in your address book.') ?></p>
+                </div>
             </div>
         <?php endif ?>
     </div>
 </div>
 
-<div class="block addresses list">
-    <div class="title"><strong><?php echo __('Additional Address Entries') ?></strong></div>
-    <div class="content">
+<div class="block block-addresses-list">
+    <div class="block-title"><strong><?php echo __('Additional Address Entries') ?></strong></div>
+    <div class="block-content">
         <?php if($_pAddsses = $this->getAdditionalAddresses()): ?>
             <ol class="items addresses">
                 <?php foreach($_pAddsses as $_address): ?>
diff --git a/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml b/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml
index e33005da72056fae9528e8392a22c0574e449788..3b5617d2d1d78c98cb64fff2af4e09ca13faef10 100644
--- a/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml
+++ b/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml
@@ -29,7 +29,7 @@
  * @var $this \Magento\Customer\Block\Address\Edit
  */
 ?>
-<form class="form address edit" action="<?php echo $this->getSaveUrl() ?>" method="post" id="form-validate" enctype="multipart/form-data" data-hasrequired="<?php echo __('* Required Fields') ?>">
+<form class="form-address-edit" action="<?php echo $this->getSaveUrl() ?>" method="post" id="form-validate" enctype="multipart/form-data" data-hasrequired="<?php echo __('* Required Fields') ?>">
     <fieldset class="fieldset">
         <legend class="legend"><span><?php echo __('Contact Information') ?></span></legend><br>
         <?php echo $this->getBlockHtml('formkey')?>
diff --git a/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml b/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml
index a66afc07a49c217628f7ff850c79e97742bab6e3..13ed3a52c04585ba6ffe225442fe072f42cf9c49 100755
--- a/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml
+++ b/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml
@@ -24,7 +24,7 @@
 
 /** @var \Magento\Customer\Block\Form\Edit $this */
 ?>
-<form class="form edit account" action="<?php echo $this->getUrl('customer/account/editPost') ?>" method="post" id="form-validate" enctype="multipart/form-data" data-hasrequired="<?php echo __('* Required Fields') ?>" autocomplete="off">
+<form class="form form-edit-account" action="<?php echo $this->getUrl('customer/account/editPost') ?>" method="post" id="form-validate" enctype="multipart/form-data" data-hasrequired="<?php echo __('* Required Fields') ?>" autocomplete="off">
     <fieldset class="fieldset info">
         <?php echo $this->getBlockHtml('formkey')?>
         <legend class="legend"><span><?php echo __('Account Information') ?></span></legend><br>
diff --git a/app/code/Magento/Customer/view/frontend/templates/form/newsletter.phtml b/app/code/Magento/Customer/view/frontend/templates/form/newsletter.phtml
index 66643d94ef1e7bc45c5a3618e6efc0834d038863..7bcfebe5f80495822e6c1900d0e7b05912553345 100644
--- a/app/code/Magento/Customer/view/frontend/templates/form/newsletter.phtml
+++ b/app/code/Magento/Customer/view/frontend/templates/form/newsletter.phtml
@@ -23,7 +23,7 @@
  */
 ?>
 <?php echo $this->getChildHtml('form_before')?>
-    <form class="form newsletter manage" action="<?php echo $this->getAction() ?>" method="post" id="form-validate">
+    <form class="form form-newsletter-manage" action="<?php echo $this->getAction() ?>" method="post" id="form-validate">
         <fieldset class="fieldset">
             <?php echo $this->getBlockHtml('formkey')?>
             <legend class="legend"><span><?php echo __('Subscription option') ?></span></legend><br>
diff --git a/app/code/Magento/Dhl/Model/Carrier.php b/app/code/Magento/Dhl/Model/Carrier.php
index 6b24d9a09baf9e27332d158fd03a36059c3fae78..7bd9e54369fac9d66dce329cf31546795866e502 100644
--- a/app/code/Magento/Dhl/Model/Carrier.php
+++ b/app/code/Magento/Dhl/Model/Carrier.php
@@ -1543,7 +1543,9 @@ class Carrier extends \Magento\Dhl\Model\AbstractDhl implements \Magento\Shippin
         $xml->addChild('LabelImageFormat', 'PDF', '');
 
         $request = $xml->asXML();
-        $request = utf8_encode($request);
+        if (!$request && !mb_detect_encoding($request) == 'UTF-8') {
+            $request = utf8_encode($request);
+        }
 
         $responseBody = $this->_getCachedQuotes($request);
         if ($responseBody === null) {
@@ -1554,6 +1556,7 @@ class Carrier extends \Magento\Dhl\Model\AbstractDhl implements \Magento\Shippin
                 $client->setConfig(array('maxredirects' => 0, 'timeout' => 30));
                 $client->setRawData($request);
                 $responseBody = $client->request(\Magento\Framework\HTTP\ZendClient::POST)->getBody();
+                $responseBody = utf8_decode($responseBody);
                 $debugData['result'] = $responseBody;
                 $this->_setCachedQuotes($request, $responseBody);
             } catch (\Exception $e) {
diff --git a/app/code/Magento/Downloadable/view/frontend/templates/checkout/cart/item/default.phtml b/app/code/Magento/Downloadable/view/frontend/templates/checkout/cart/item/default.phtml
index 282a84c4963e2a3fa5a25f40f3916116b5a19e8d..23e86d8f57de95ea67a222748a55972cf9ce8bcf 100644
--- a/app/code/Magento/Downloadable/view/frontend/templates/checkout/cart/item/default.phtml
+++ b/app/code/Magento/Downloadable/view/frontend/templates/checkout/cart/item/default.phtml
@@ -29,17 +29,17 @@ $canApplyMsrp = $this->helper('Magento\Catalog\Helper\Data')->canApplyMsrp($_ite
 ?>
 <?php echo $this->getChildHtml('item_extra') ?>
 <tbody class="cart item">
-    <tr class="item info">
+    <tr class="item info item-info">
         <td class="col item">
             <?php if ($this->hasProductUrl()): ?>
                 <a href="<?php echo $this->getProductUrl() ?>"
                    title="<?php echo $this->escapeHtml($this->getProductName()) ?>"
-                   class="product photo">
+                   class="product photo product-item-photo">
             <?php endif; ?>
             <?php echo $this->getLayout()->createBlock('Magento\Catalog\Block\Product\Image')->init($_item->getProduct(), 'cart_page_product_thumbnail')->toHtml(); ?>
             <?php if ($this->hasProductUrl()):?></a><?php endif;?>
-            <div class="product details">
-                <strong class="product name">
+            <div class="product details product-item-details">
+                <strong class="product name product-item-name">
                     <?php if ($this->hasProductUrl()):?>
                         <a href="<?php echo $this->getProductUrl() ?>"><?php echo $this->escapeHtml($this->getProductName()) ?></a>
                     <?php else: ?>
@@ -47,7 +47,7 @@ $canApplyMsrp = $this->helper('Magento\Catalog\Helper\Data')->canApplyMsrp($_ite
                     <?php endif; ?>
                 </strong>
                 <?php if ($_options = $this->getOptionList()):?>
-                    <dl class="cart item options">
+                    <dl class="cart-item-options">
                         <?php foreach ($_options as $_option) : ?>
                             <?php $_formatedOptionValue = $this->getFormatedOptionValue($_option) ?>
                             <dt><?php echo $this->escapeHtml($_option['label']) ?></dt>
@@ -67,7 +67,7 @@ $canApplyMsrp = $this->helper('Magento\Catalog\Helper\Data')->canApplyMsrp($_ite
                 <?php endif;?>
                 <?php if ($messages = $this->getMessages()): ?>
                     <?php foreach ($messages as $message): ?>
-                        <p class="cart item message <?php echo $message['type'] ?>">* <?php echo $this->escapeHtml($message['text']) ?></p>
+                        <div class="cart item message <?php echo $message['type'] ?>"><div><?php echo $this->escapeHtml($message['text']) ?></div></div>
                     <?php endforeach; ?>
                 <?php endif; ?>
                 <?php $addInfoBlock = $this->getProductAdditionalInformationBlock(); ?>
@@ -90,89 +90,94 @@ $canApplyMsrp = $this->helper('Magento\Catalog\Helper\Data')->canApplyMsrp($_ite
             <?php $cols++; ?>
         </td>
     <?php else: ?>
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displayCartPriceExclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()): ?>
-        <td class="col price excl tax" data-th="<?php echo __('Unit Price Excl. Tax'); ?>">
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-            <span class="cart tax total"
-                  data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $_item->getId(); ?>"}'>
-            <?php else: ?>
-                <span class="cart price">
-            <?php endif; ?>
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getCalculationPrice()+$_item->getWeeeTaxAppliedAmount()+$_item->getWeeeTaxDisposition()); ?>
-            <?php else: ?>
-                <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getCalculationPrice()) ?>
-            <?php endif; ?>
-            </span>
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item)): ?>
-                <div class="cart tax info" id="eunit-item-tax-details<?php echo $_item->getId(); ?>" style="display:none;">
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displayCartPriceExclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartPriceInclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()): ?>
+        <td class="col price" data-th="<?php echo $this->escapeHtml(__('Price')); ?>">
+            <?php if ($this->helper('Magento\Tax\Helper\Data')->displayCartPriceInclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()): ?>
+            <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
+                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($_item); ?>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                    <span class="cart-tax-total"
+                        data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $_item->getId(); ?>"}'>
+                <?php else: ?>
+                    <span class="cart price">
+                <?php endif; ?>
+
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedAmount()); ?>
+                <?php else: ?>
+                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl-$_item->getWeeeTaxDisposition()) ?>
+                <?php endif; ?>
+                </span>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item)): ?>
+
+                <div class="cart-tax-info" id="unit-item-tax-details<?php echo $_item->getId(); ?>" style="display:none;">
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
                         <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                            <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount'],true,true); ?></span>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount'],true,true); ?></span>
                         <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
                         <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                            <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount_incl_tax'],true,true); ?></span>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount_incl_tax'],true,true); ?></span>
                         <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
                         <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                            <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount_incl_tax'],true,true); ?></span>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount_incl_tax'],true,true); ?></span>
                         <?php endforeach; ?>
                     <?php endif; ?>
                 </div>
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <div class="cart tax total"
-                         data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $_item->getId(); ?>"}'>
-                        <span class="weee"><?php echo __('Total'); ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getCalculationPrice()+$_item->getWeeeTaxAppliedAmount()+$_item->getWeeeTaxDisposition()); ?></span>
+
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                    <div class="cart-tax-total"
+                         data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $_item->getId(); ?>"}'>
+                        <span class="weee" data-th="<?php echo __('Total incl. tax'); ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedAmount()); ?></span>
                     </div>
                 <?php endif; ?>
+                <?php endif; ?>
+                <?php $cols++; ?>
+            </span>
             <?php endif; ?>
-            <?php $cols++; ?>
-        </td>
-        <?php endif; ?>
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displayCartPriceInclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()): ?>
-            <td class="col price incl tax" data-th="<?php echo __('Unit Price Incl. Tax'); ?>">
-                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($_item); ?>
+
+            <?php if ($this->helper('Magento\Tax\Helper\Data')->displayCartPriceExclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()): ?>
+                <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                <span class="cart tax total"
-                      data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $_item->getId(); ?>"}'>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $_item->getId(); ?>"}'>
                 <?php else: ?>
-                    <span class="cart price">
+                        <span class="cart price">
                 <?php endif; ?>
-
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedAmount()); ?>
+                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getCalculationPrice()+$_item->getWeeeTaxAppliedAmount()+$_item->getWeeeTaxDisposition()); ?>
                 <?php else: ?>
-                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl-$_item->getWeeeTaxDisposition()) ?>
+                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getCalculationPrice()) ?>
                 <?php endif; ?>
                 </span>
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item)): ?>
-
-                    <div class="cart tax info" id="unit-item-tax-details<?php echo $_item->getId(); ?>" style="display:none;">
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item)): ?>
+                    <div class="cart-tax-info" id="eunit-item-tax-details<?php echo $_item->getId(); ?>" style="display:none;">
                         <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                                <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount'],true,true); ?></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount'],true,true); ?></span>
                             <?php endforeach; ?>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                                <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount_incl_tax'],true,true); ?></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount_incl_tax'],true,true); ?></span>
                             <?php endforeach; ?>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                                <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount_incl_tax'],true,true); ?></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['amount_incl_tax'],true,true); ?></span>
                             <?php endforeach; ?>
                         <?php endif; ?>
                     </div>
-
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                            <div class="cart tax total"
-                                 data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $_item->getId(); ?>"}'>
-                            <span class="weee"><?php echo __('Total incl. tax'); ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedAmount()); ?></span>
+                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                        <div class="cart-tax-total"
+                             data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $_item->getId(); ?>"}'>
+                            <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getCalculationPrice()+$_item->getWeeeTaxAppliedAmount()+$_item->getWeeeTaxDisposition()); ?></span>
                         </div>
                     <?php endif; ?>
                 <?php endif; ?>
-                <?php $cols++; ?>
-            </td>
+            </span>
+            <?php endif; ?>
+            <?php $cols++; ?>
+        </td>
         <?php endif; ?>
     <?php endif; ?>
         <td class="col qty">
@@ -181,101 +186,105 @@ $canApplyMsrp = $this->helper('Magento\Catalog\Helper\Data')->canApplyMsrp($_ite
             </div>
             <?php $cols++; ?>
         </td>
-    <?php if (($this->helper('Magento\Tax\Helper\Data')->displayCartPriceExclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()) && !$_item->getNoSubtotal()): ?>
-        <td class="col subtotal excl tax" data-th="<?php echo __('Subtotal Excl. Tax'); ?>">
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-            <span class="cart tax total"
-                  data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
-            <?php else: ?>
-                <span class="cart price">
-            <?php endif; ?>
 
-            <?php if ($canApplyMsrp): ?>
-                <span class="cart msrp subtotal">--</span>
-            <?php else: ?>
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getRowTotal()+$_item->getWeeeTaxAppliedRowAmount()+$_item->getWeeeTaxRowDisposition()); ?>
+        <?php if (($this->helper('Magento\Tax\Helper\Data')->displayCartPriceInclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartPriceExclTax() ||$this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()) && !$_item->getNoSubtotal()): ?>
+            <td class="col subtotal" data-th="<?php echo $this->escapeHtml(__('Subtotal'));?>">
+                <?php if (($this->helper('Magento\Tax\Helper\Data')->displayCartPriceInclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()) && !$_item->getNoSubtotal()): ?>
+                <span class="incl tax" data-th="<?php echo __('Incl. Tax'); ?>">
+                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($_item); ?>
+                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
                 <?php else: ?>
-                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getRowTotal()) ?>
+                    <span class="cart price">
                 <?php endif; ?>
-            <?php endif; ?>
+                    <?php if ($canApplyMsrp): ?>
+                        <span class="cart msrp subtotal">--</span>
+                    <?php else: ?>
+                        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                            <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedRowAmount()); ?>
+                        <?php else: ?>
+                            <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl-$_item->getWeeeTaxRowDisposition()) ?>
+                        <?php endif; ?>
+                    <?php endif; ?>
+                    </span>
 
-            </span>
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item)): ?>
+                    <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item)): ?>
+                        <div class="cart-tax-info" id="subtotal-item-tax-details<?php echo $_item->getId(); ?>" style="display:none;">
+                            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
+                                    <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount'],true,true); ?></span>
+                                <?php endforeach; ?>
+                            <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
+                                    <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount_incl_tax'],true,true); ?></span>
+                                <?php endforeach; ?>
+                            <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
+                                    <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount_incl_tax'],true,true); ?></span>
+                                <?php endforeach; ?>
+                            <?php endif; ?>
+                        </div>
 
-                <div class="cart tax info" id="esubtotal-item-tax-details<?php echo $_item->getId(); ?>" style="display:none;">
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                            <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount'],true,true); ?></span>
-                        <?php endforeach; ?>
-                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                            <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount_incl_tax'],true,true); ?></span>
-                        <?php endforeach; ?>
-                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                            <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount_incl_tax'],true,true); ?></span>
-                        <?php endforeach; ?>
+                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                        <div class="cart-tax-total"
+                             data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
+                            <span class="weee" data-th="<?php echo __('Total incl. tax'); ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedRowAmount()); ?></span>
+                        </div>
                     <?php endif; ?>
-                </div>
-
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <div class="cart tax total"
-                         data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
-                        <span class="weee"><?php echo __('Total'); ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getRowTotal()+$_item->getWeeeTaxAppliedRowAmount()+$_item->getWeeeTaxRowDisposition()); ?></span>
-                    </div>
-                <?php endif; ?>
+                    <?php endif; ?>
+                </span>
             <?php endif; ?>
-            <?php $cols++; ?>
-        </td>
-    <?php endif; ?>
-    <?php if (($this->helper('Magento\Tax\Helper\Data')->displayCartPriceInclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()) && !$_item->getNoSubtotal()): ?>
-        <td class="col subtotal incl tax" data-th="<?php echo __('Subtotal Incl. Tax'); ?>">
-            <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($_item); ?>
+
+            <?php if (($this->helper('Magento\Tax\Helper\Data')->displayCartPriceExclTax() || $this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()) && !$_item->getNoSubtotal()): ?>
+            <span class="excl tax" data-th="<?php echo __('Excl. Tax'); ?>">
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-            <span class="cart tax total"
-                  data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
-            <?php else: ?>
-                <span class="cart price">
-            <?php endif; ?>
-                <?php if ($canApplyMsrp): ?>
-                    <span class="cart msrp subtotal">--</span>
+                <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
                 <?php else: ?>
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                        <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedRowAmount()); ?>
-                    <?php else: ?>
-                        <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl-$_item->getWeeeTaxRowDisposition()) ?>
-                    <?php endif; ?>
+                    <span class="cart price">
                 <?php endif; ?>
-            </span>
 
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item)): ?>
-                <div class="cart tax info" id="subtotal-item-tax-details<?php echo $_item->getId(); ?>" style="display:none;">
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                            <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount'],true,true); ?></span>
-                        <?php endforeach; ?>
-                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                            <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount_incl_tax'],true,true); ?></span>
-                        <?php endforeach; ?>
-                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
-                            <span class="weee"><?php echo $tax['title']; ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount_incl_tax'],true,true); ?></span>
-                        <?php endforeach; ?>
+                    <?php if ($canApplyMsrp): ?>
+                        <span class="cart msrp subtotal">--</span>
+                    <?php else: ?>
+                        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                            <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getRowTotal()+$_item->getWeeeTaxAppliedRowAmount()+$_item->getWeeeTaxRowDisposition()); ?>
+                        <?php else: ?>
+                            <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getRowTotal()) ?>
+                        <?php endif; ?>
                     <?php endif; ?>
-                </div>
 
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
-                    <div class="cart tax total"
-                         data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
-                        <span class="weee"><?php echo __('Total incl. tax'); ?>: <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_incl+$_item->getWeeeTaxAppliedRowAmount()); ?></span>
-                    </div>
+                    </span>
+                    <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item)): ?>
+                        <div class="cart-tax-info" id="esubtotal-item-tax-details<?php echo $_item->getId(); ?>" style="display:none;">
+                            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
+                                    <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount'],true,true); ?></span>
+                                <?php endforeach; ?>
+                            <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
+                                    <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount_incl_tax'],true,true); ?></span>
+                                <?php endforeach; ?>
+                            <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($_item) as $tax): ?>
+                                    <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($tax['row_amount_incl_tax'],true,true); ?></span>
+                                <?php endforeach; ?>
+                            <?php endif; ?>
+                        </div>
+
+                        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && $_item->getWeeeTaxAppliedAmount()): ?>
+                            <div class="cart-tax-total"
+                                 data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $_item->getId(); ?>"}'>
+                                <span class="weee" data-th="<?php echo __('Total'); ?>"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_item->getRowTotal()+$_item->getWeeeTaxAppliedRowAmount()+$_item->getWeeeTaxRowDisposition()); ?></span>
+                            </div>
+                        <?php endif; ?>
+                    <?php endif; ?>
+                </span>
                 <?php endif; ?>
-            <?php endif; ?>
-            <?php $cols++; ?>
-        </td>
-    <?php endif; ?>
+                <?php $cols++; ?>
+            </td>
+        <?php endif; ?>
     </tr>
     <tr class="item actions">
         <td colspan="<?php echo $cols;?>">
diff --git a/app/code/Magento/Downloadable/view/frontend/templates/customer/products/list.phtml b/app/code/Magento/Downloadable/view/frontend/templates/customer/products/list.phtml
index 0c27f2d190b65369531400cd59cbffa80dc11ffe..5353cba99ec8a1ebe88c7046b4853bcff6d6337c 100644
--- a/app/code/Magento/Downloadable/view/frontend/templates/customer/products/list.phtml
+++ b/app/code/Magento/Downloadable/view/frontend/templates/customer/products/list.phtml
@@ -29,43 +29,49 @@
 ?>
 <?php $_items = $this->getItems(); ?>
 <?php if(count($_items)): ?>
-    <div class="downloadable products toolbar">
-        <?php echo $this->getChildHtml('pager'); ?>
-    </div>
-    <div class="wrapper table downloadable products">
-        <table id="my-downloadable-products-table" class="data table downloadable products">
+    <?php if ($this->getChildHtml('pager')): ?>
+        <div class="toolbar downloadable-products-toolbar top">
+            <?php echo $this->getChildHtml('pager'); ?>
+        </div>
+    <?php endif; ?>
+    <div class="table-wrapper downloadable-products">
+        <table id="my-downloadable-products-table" class="data table table-downloadable-products">
             <caption class="table caption"><?php echo __('Downloadable Products') ?></caption>
             <thead>
                 <tr>
-                    <th class="col id"><?php echo __('Order #') ?></th>
-                    <th class="col date"><?php echo __('Date') ?></th>
-                    <th class="col title"><?php echo __('Title') ?></th>
-                    <th class="col status"><?php echo __('Status') ?></th>
-                    <th class="col remaining"><?php echo __('Remaining Downloads') ?></th>
+                    <th scope="col" class="col id"><?php echo __('Order #') ?></th>
+                    <th scope="col" class="col date"><?php echo __('Date') ?></th>
+                    <th scope="col" class="col title"><?php echo __('Title') ?></th>
+                    <th scope="col" class="col status"><?php echo __('Status') ?></th>
+                    <th scope="col" class="col remaining"><?php echo __('Remaining Downloads') ?></th>
                 </tr>
             </thead>
             <tbody>
             <?php foreach ($_items as $_item): ?>
                 <tr>
-                    <td class="col id">
-                        <a href="<?php echo $this->getOrderViewUrl($_item->getPurchased()->getOrderId()) ?>" title="<?php echo __('View Order') ?>">
+                    <td data-th="<?php echo $this->escapeHtml(__('Order #')) ?>" class="col id">
+                        <a href="<?php echo $this->getOrderViewUrl($_item->getPurchased()->getOrderId()) ?>" 
+                            title="<?php echo $this->escapeHtml(__('View Order')) ?>">
                             <?php echo $_item->getPurchased()->getOrderIncrementId() ?>
                         </a>
                     </td>
-                    <td class="col date"><?php echo $this->formatDate($_item->getPurchased()->getCreatedAt()) ?></td>
-                    <td class="col title">
-                        <?php echo $this->escapeHtml($_item->getPurchased()->getProductName()) ?> - <a href="<?php echo $this->getDownloadUrl($_item) ?>" title="<?php echo __('Start Download') ?>" <?php echo $this->getIsOpenInNewWindow()?'onclick="this.target=\'_blank\'"':''; ?>><?php echo $this->escapeHtml($_item->getLinkTitle()) ?></a>
+                    <td data-th="<?php echo $this->escapeHtml(__('Date')) ?>" class="col date"><?php echo $this->formatDate($_item->getPurchased()->getCreatedAt()) ?></td>
+                    <td data-th="<?php echo $this->escapeHtml(__('Title')) ?>" class="col title">
+                        <strong class="product-name"><?php echo $this->escapeHtml($_item->getPurchased()->getProductName()) ?></strong>
+                        <a href="<?php echo $this->getDownloadUrl($_item) ?>" title="<?php echo $this->escapeHtml(__('Start Download')) ?>" class="action download" <?php echo $this->getIsOpenInNewWindow()?'onclick="this.target=\'_blank\'"':''; ?>><?php echo $this->escapeHtml($_item->getLinkTitle()) ?></a>
                     </td>
-                    <td class="col status"><?php echo __(ucfirst($_item->getStatus())) ?></td>
-                    <td class="col remaining"><?php echo $this->getRemainingDownloads($_item) ?></td>
+                    <td data-th="<?php echo $this->escapeHtml(__('Status')) ?>" class="col status"><?php echo __(ucfirst($_item->getStatus())) ?></td>
+                    <td data-th="<?php echo $this->escapeHtml(__('Remaining Downloads')) ?>" class="col remaining"><?php echo $this->getRemainingDownloads($_item) ?></td>
                 </tr>
             <?php endforeach; ?>
             </tbody>
         </table>
     </div>
-    <div class="downloadable products toolbar">
-        <?php echo $this->getChildHtml('pager'); ?>
-    </div>
+    <?php if ($this->getChildHtml('pager')): ?>
+        <div class="toolbar downloadable-products-toolbar bottom">
+            <?php echo $this->getChildHtml('pager'); ?>
+        </div>
+    <?php endif; ?>
 <?php else: ?>
     <div class="message info empty"><span><?php echo __('You have not purchased any downloadable products yet.'); ?></span></div>
 <?php endif; ?>
diff --git a/app/code/Magento/Downloadable/view/frontend/templates/sales/order/creditmemo/items/renderer/downloadable.phtml b/app/code/Magento/Downloadable/view/frontend/templates/sales/order/creditmemo/items/renderer/downloadable.phtml
index 57684d83378a187500445ee6b277d28f17a44963..ee4566eed5f24f1800b30725660297a413c33af4 100644
--- a/app/code/Magento/Downloadable/view/frontend/templates/sales/order/creditmemo/items/renderer/downloadable.phtml
+++ b/app/code/Magento/Downloadable/view/frontend/templates/sales/order/creditmemo/items/renderer/downloadable.phtml
@@ -27,10 +27,10 @@
 <?php $_item = $this->getItem() ?>
 <?php $_order = $this->getItem()->getOrderItem()->getOrder() ?>
 <tr class="border" id="order-item-row-<?php echo $_item->getId() ?>">
-    <td class="col name">
-        <strong class="product name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
+    <td class="col name" data-th="<?php echo $this->escapeHtml(__('Product Name')); ?>">
+        <strong class="product name product-item-name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
         <?php if($_options = $this->getItemOptions()): ?>
-            <dl class="item options">
+            <dl class="item options links">
                 <?php foreach ($_options as $_option) : ?>
                     <dt><?php echo $this->escapeHtml($_option['label']) ?></dt>
                     <?php if (!$this->getPrintStatus()): ?>
@@ -54,7 +54,7 @@
         <?php endif; ?>
         <?php /* downloadable */?>
         <?php if ($links = $this->getLinks()): ?>
-            <dl class="item options">
+            <dl class="item options links">
                 <dt><?php echo $this->getLinksTitle() ?></dt>
                 <?php foreach ($links->getPurchasedItems() as $link): ?>
                     <dd><?php echo $this->escapeHtml($link->getLinkTitle()); ?></dd>
@@ -74,78 +74,13 @@
                data-item-id="<?php echo $_item->getId() ?>"><?php echo __('Gift Message') ?></a>
         <?php endif; ?>
     </td>
-    <td  class="col sku"><?php echo $this->prepareSku($this->getSku()) ?></td>
-    <td class="col price">
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-            <span class="price excl tax">
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart price">
-                <?php endif; ?>
-                <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    </span>
-                <?php endif; ?>
-            <?php endif; ?>
-        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-            <span class="cart tax total"
-                  data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-        <?php else: ?>
-            <span class="cart price">
-        <?php endif; ?>
-
-        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-            <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
-        <?php else: ?>
-            <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
-        <?php endif; ?>
-        </span>
-
-        <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-            <span class="cart tax info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <small>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?>
-                        <?php endforeach; ?>
-                    </small>
-                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                        <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small>
-                    <?php endforeach; ?>
-                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <small>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?>
-                        <?php endforeach; ?>
-                    </small>
-                <?php endif; ?>
-            </span>
-
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <span class="cart tax total"
-                      data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                    <?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
-                </span>
-            <?php endif; ?>
-        <?php endif; ?>
-        </span>
-        <br />
-        <?php endif; ?>
+    <td class="col sku" data-th="<?php echo $this->escapeHtml(__('SKU')); ?>"><?php echo $this->prepareSku($this->getSku()) ?></td>
+    <td class="col price" data-th="<?php echo $this->escapeHtml(__('Price')); ?>">
         <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-            <span class="price incl tax">
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart price">
-                <?php endif; ?>
-                <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    </span>
-                <?php endif; ?>
-            <?php endif; ?>
+            <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
             <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <span class="cart tax total"
+                <span class="cart-tax-total"
                       data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
             <?php else: ?>
                 <span class="cart price">
@@ -158,150 +93,161 @@
             </span>
 
             <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                <span class="cart tax info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
+                <span class="cart tax info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?>
-                            <?php endforeach; ?>
-                        </small>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                        <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                         <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
                         <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?>
-                            <?php endforeach; ?>
-                        </small>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                        <?php endforeach; ?>
                     <?php endif; ?>
                 </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart tax total"
+                    <span class="cart-tax-total"
                           data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                        <?php echo __('Total incl. tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?></span>
                     </span>
                 <?php endif; ?>
             <?php endif; ?>
             </span>
         <?php endif; ?>
-    </td>
-    <td class="col qty"><?php echo $_item->getQty()*1 ?></td>
-    <td class="col subtotal">
         <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-        <span class="price excl tax">
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart price">
-                <?php endif; ?>
-                <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    </span>
-                <?php endif; ?>
-            <?php endif; ?>
+            <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-            <span class="cart tax total"
-                  data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
             <?php else: ?>
-            <span class="cart price">
+                <span class="cart price">
             <?php endif; ?>
+
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
             <?php else: ?>
-                <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
             <?php endif; ?>
-            </span>
+                </span>
 
             <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                <span class="cart tax info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?>
-                            <?php endforeach; ?>
-                        </small>
-                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></small>
-                        <?php endforeach; ?>
-                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?>
-                            <?php endforeach; ?>
-                        </small>
-                    <?php endif; ?>
-                    </span>
-
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart tax total"
-                          data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                        <?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
-                    </span>
+                <span class="cart-tax-info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                    <?php endforeach; ?>
+                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
+                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
                 <?php endif; ?>
-            <?php endif; ?>
             </span>
-            <br />
+
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+            <span class="cart-tax-total"
+                  data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?></span>
+            </span>
             <?php endif; ?>
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-            <span class="price incl tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart price">
-                    <?php endif; ?>
-                        <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
+        <?php endif; ?>
+        </span>
+        <?php endif; ?>
+    </td>
+    <td class="col qty" data-th="<?php echo $this->escapeHtml(__('Qty')); ?>"><?php echo $_item->getQty()*1 ?></td>
+    <td class="col subtotal" data-th="<?php echo $this->escapeHtml(__('Subtotal')); ?>">
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
+            <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
                 <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($this->getItem()); ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <span class="cart tax total"
+                <span class="cart-tax-total"
                       data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
                 <?php else: ?>
-                <span class="cart price">
+                    <span class="cart price">
                 <?php endif; ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                     <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?>
                 <?php else: ?>
                     <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxRowDisposition()) ?>
                 <?php endif; ?>
-            </span>
+                    </span>
 
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                <span class="cart tax info" id="subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+                    <span class="cart-tax-info" id="subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?>
-                            <?php endforeach; ?>
-                        </small>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                        <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                         <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></small>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
                         <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?>
-                            <?php endforeach; ?>
-                        </small>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                        <?php endforeach; ?>
                     <?php endif; ?>
                 </span>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart tax total"
+                    <span class="cart-tax-total"
                           data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                        <?php echo __('Total incl. tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?>
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?></span>
                     </span>
                 <?php endif; ?>
             <?php endif; ?>
         </span>
         <?php endif; ?>
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
+            <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+            <?php else: ?>
+                <span class="cart price">
+            <?php endif; ?>
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
+            <?php else: ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
+            <?php endif; ?>
+                </span>
+
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+                <span class="cart-tax-info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                    <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                <?php endforeach; ?>
+            <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                    <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                <?php endforeach; ?>
+            <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                    <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                <?php endforeach; ?>
+            <?php endif; ?>
+            </span>
+
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                    <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?></span>
+            </span>
+            <?php endif; ?>
+        <?php endif; ?>
+        </span>
+        <?php endif; ?>
     </td>
-    <td class="col discount"><?php echo $_order->formatPrice(-$_item->getDiscountAmount()) ?></td>
-    <td class="cot total">
+    <td class="col discount" data-th="<?php echo $this->escapeHtml(__('Discount Amount')); ?>"><?php echo $_order->formatPrice(-$_item->getDiscountAmount()) ?></td>
+    <td class="cot total" data-th="<?php echo $this->escapeHtml(__('Row Total')); ?>">
         <?php echo $_order->formatPrice($_item->getRowTotal()-$_item->getDiscountAmount()+$_item->getTaxAmount()+$_item->getWeeeTaxAppliedRowAmount()) ?>
     </td>
 </tr>
diff --git a/app/code/Magento/Downloadable/view/frontend/templates/sales/order/invoice/items/renderer/downloadable.phtml b/app/code/Magento/Downloadable/view/frontend/templates/sales/order/invoice/items/renderer/downloadable.phtml
index 363ed5c6aee041415fe501b652847f56a60be27b..ca56ccf7ff20d02b13df137ac9f9bf08618248d1 100644
--- a/app/code/Magento/Downloadable/view/frontend/templates/sales/order/invoice/items/renderer/downloadable.phtml
+++ b/app/code/Magento/Downloadable/view/frontend/templates/sales/order/invoice/items/renderer/downloadable.phtml
@@ -27,10 +27,10 @@
 <?php $_item = $this->getItem() ?>
 <?php $_order = $this->getItem()->getOrderItem()->getOrder() ?>
 <tr id="order-item-row-<?php echo $_item->getId() ?>">
-    <td class="col name">
-        <strong class="product name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
+    <td class="col name" data-th="<?php echo $this->escapeHtml(__('Product Name')); ?>">
+        <strong class="product name product-item-name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
         <?php if($_options = $this->getItemOptions()): ?>
-            <dl class="item options">
+            <dl class="item options links">
                 <?php foreach ($_options as $_option) : ?>
                     <dt><?php echo $this->escapeHtml($_option['label']) ?></dt>
                     <?php if (!$this->getPrintStatus()): ?>
@@ -54,7 +54,7 @@
         <?php endif; ?>
         <?php /* downloadable */ ?>
         <?php if ($links = $this->getLinks()): ?>
-            <dl class="item options">
+            <dl class="item options links">
                 <dt><?php echo $this->getLinksTitle() ?></dt>
                 <?php foreach ($links->getPurchasedItems() as $link): ?>
                     <dd><?php echo $this->escapeHtml($link->getLinkTitle()); ?></dd>
@@ -73,236 +73,182 @@
                data-item-id="<?php echo $_item->getId() ?>"><?php echo __('Gift Message') ?></a>
         <?php endif; ?>
     </td>
-    <td class="col sku"><?php echo $this->prepareSku($this->getSku()) ?></td>
-    <td class="col price">
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-            <span class="price excl tax">
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart price">
-                <?php endif; ?>
-                <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    </span>
-                <?php endif; ?>
-            <?php endif; ?>
+    <td class="col sku" data-th="<?php echo $this->escapeHtml(__('SKU')); ?>"><?php echo $this->prepareSku($this->getSku()) ?></td>
+    <td class="col price" data-th="<?php echo $this->escapeHtml(__('Price')); ?>">
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
+            <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
+            <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <span class="cart tax total"
-                      data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
             <?php else: ?>
-            <span class="cart price">
+                <span class="cart price">
             <?php endif; ?>
+
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
+                <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
             <?php else: ?>
-                <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
+                <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
             <?php endif; ?>
-            </span>
-
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                <span class="cart tax info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"
-                      style="display:none;">
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?>
-                            <?php endforeach; ?>
-                        </small>
-                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small>
-                        <?php endforeach; ?>
-                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?>
-                            <?php endforeach; ?>
-                        </small>
-                    <?php endif; ?>
                 </span>
 
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart tax total"
-                          data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                        <?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
-                    </span>
-                <?php endif; ?>
-            <?php endif; ?>
-            </span>
-            <br />
-        <?php endif; ?>
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-            <span class="price incl tax">
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart price">
-                <?php endif; ?>
-                <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    </span>
-                <?php endif; ?>
-            <?php endif; ?>
-            <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <span class="cart tax total"
-                      data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-            <?php else: ?>
-            <span class="cart price">
-        <?php endif; ?>
-
-        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-            <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
-        <?php else: ?>
-            <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
-        <?php endif; ?>
-        </span>
-
-        <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-            <span class="cart tax info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+            <span class="cart-tax-info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <small>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?>
-                        <?php endforeach; ?>
-                    </small>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                    <?php endforeach; ?>
                 <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                     <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                        <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
                     <?php endforeach; ?>
                 <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <small>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?>
-                        <?php endforeach; ?>
-                    </small>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
                 <?php endif; ?>
             </span>
 
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <span class="cart tax total"
+                <span class="cart-tax-total"
                       data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                    <?php echo __('Total incl. tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
+                    <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?></span>
                 </span>
             <?php endif; ?>
         <?php endif; ?>
         </span>
         <?php endif; ?>
-    </td>
-    <td class="col qty">
-        <span class="qty summary"><?php echo $_item->getQty()*1 ?></span>
-    </td>
-    <td class="col subtotal">
         <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-        <span class="price excl tax">
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart price">
-                <?php endif; ?>
-                <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    </span>
-                <?php endif; ?>
-            <?php endif; ?>
+            <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-            <span class="cart tax total"
-                  data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
             <?php else: ?>
-            <span class="cart price">
+                <span class="cart price">
             <?php endif; ?>
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
-                <?php else: ?>
-                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
-                <?php endif; ?>
-            </span>
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
+            <?php else: ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
+            <?php endif; ?>
+                </span>
 
             <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                <span class="cart tax info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
+                <span class="cart-tax-info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"
+                      style="display: none;">
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?>
-                            <?php endforeach; ?>
-                        </small>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                        <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                         <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></small>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
                         <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?>
-                            <?php endforeach; ?>
-                        </small>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                        <?php endforeach; ?>
                     <?php endif; ?>
                 </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart tax total"
-                          data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                        <?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?></span>
                     </span>
                 <?php endif; ?>
             <?php endif; ?>
             </span>
-            <br />
         <?php endif; ?>
+    </td>
+    <td class="col qty" data-th="<?php echo $this->escapeHtml(__('Qty Invoiced')); ?>">
+        <span class="qty summary" data-th="<?php echo $this->escapeHtml(__('Qty Invoiced')); ?>"><?php echo $_item->getQty()*1 ?></span>
+    </td>
+    <td class="col subtotal" data-th="<?php echo $this->escapeHtml(__('Subtotal')); ?>">
         <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-        <span class="price incl tax">
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart price">
-                <?php endif; ?>
-                <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    </span>
-                <?php endif; ?>
-            <?php endif; ?>
+        <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
             <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($this->getItem()); ?>
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-            <span class="cart tax total"
-                  data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                <?php else: ?>
+                <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+            <?php else: ?>
                 <span class="cart price">
-                <?php endif; ?>
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?>
-                <?php else: ?>
-                    <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxRowDisposition()) ?>
-                <?php endif; ?>
-            </span>
+            <?php endif; ?>
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?>
+            <?php else: ?>
+                <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxRowDisposition()) ?>
+            <?php endif; ?>
+                </span>
 
             <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                <span class="cart tax info"
+                <span class="cart-tax-info"
                       id="subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"
-                      style="display:none;">
+                      style="display: none;">
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?>
-                            <?php endforeach; ?>
-                        </small>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                        <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                         <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></small>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
                         <?php endforeach; ?>
                     <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?>
-                            <?php endforeach; ?>
-                        </small>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                        <?php endforeach; ?>
                     <?php endif; ?>
                 </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart tax total"
+                    <span class="cart-tax-total"
                           data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                        <?php echo __('Total incl. tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?>
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?></span>
                     </span>
                 <?php endif; ?>
             <?php endif; ?>
         </span>
         <?php endif; ?>
+            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
+            <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+            <?php else: ?>
+                <span class="cart price">
+            <?php endif; ?>
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
+            <?php else: ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
+            <?php endif; ?>
+                </span>
+
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+                <span class="cart-tax-info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                    <?php endforeach; ?>
+                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
+                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
+                <?php endif; ?>
+                    </span>
+
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?></span>
+                    </span>
+                <?php endif; ?>
+            <?php endif; ?>
+            </span>
+        <?php endif; ?>
     </td>
 </tr>
diff --git a/app/code/Magento/Downloadable/view/frontend/templates/sales/order/items/renderer/downloadable.phtml b/app/code/Magento/Downloadable/view/frontend/templates/sales/order/items/renderer/downloadable.phtml
index 2848b5b843b2afc3b083b2c6cb731a9fdd0a7683..a532caf89521fd37a3502cfc22c70d9a69f6b925 100644
--- a/app/code/Magento/Downloadable/view/frontend/templates/sales/order/items/renderer/downloadable.phtml
+++ b/app/code/Magento/Downloadable/view/frontend/templates/sales/order/items/renderer/downloadable.phtml
@@ -26,10 +26,10 @@
 ?>
 <?php $_item = $this->getItem() ?>
 <tr id="order-item-row-<?php echo $_item->getId() ?>">
-    <td class="col name">
-        <strong class="product name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
+    <td class="col name" data-th="<?php echo $this->escapeHtml(__('Product Name')); ?>">
+        <strong class="product name product-item-name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
         <?php if($_options = $this->getItemOptions()): ?>
-            <dl class="item options">
+            <dl class="item options links">
                 <?php foreach ($_options as $_option) : ?>
                     <dt><?php echo $this->escapeHtml($_option['label']) ?></dt>
                     <?php if (!$this->getPrintStatus()): ?>
@@ -55,7 +55,7 @@
         <?php endif; ?>
         <?php /* downloadable */ ?>
         <?php if ($links = $this->getLinks()): ?>
-            <dl class="item options">
+            <dl class="item options links">
                 <dt><?php echo $this->getLinksTitle() ?></dt>
                 <?php foreach ($links->getPurchasedItems() as $link): ?>
                     <dd><?php echo $this->escapeHtml($link->getLinkTitle()); ?></dd>
@@ -78,251 +78,209 @@
             </a>
         <?php endif; ?>
     </td>
-    <td class="col sku"><?php echo $this->prepareSku($this->getSku()) ?></td>
-    <td class="col price">
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-            <span class="price excl tax">
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart price">
-                <?php endif; ?>
-                <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    </span>
-                <?php endif; ?>
-            <?php endif; ?>
+    <td class="col sku" data-th="<?php echo $this->escapeHtml(__('SKU')); ?>"><?php echo $this->prepareSku($this->getSku()) ?></td>
+    <td class="col price" data-th="<?php echo $this->escapeHtml(__('Price')); ?>">
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
+            <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
+            <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-            <span class="cart tax total"
-                  data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
             <?php else: ?>
-            <span class="cart price">
+                <span class="cart price">
             <?php endif; ?>
-
             <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
+                <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
             <?php else: ?>
-                <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
+                <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
             <?php endif; ?>
-            </span>
+                </span>
 
             <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                <span class="cart tax info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"
-                      style="display:none;">
+                <span class="cart-tax-info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"
+                      style="display: none;">
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <small>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?>
-                        <?php endforeach; ?>
-                    </small>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                    <?php endforeach; ?>
                 <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                     <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                        <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small>
+                    <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
                     <?php endforeach; ?>
                 <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <small>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?>
-                        <?php endforeach; ?>
-                    </small>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
                 <?php endif; ?>
-                </span>
+            </span>
 
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart tax total"
-                          data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                        <?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
-                    </span>
-                <?php endif; ?>
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                    <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?></span>
+                </span>
+            <?php endif; ?>
             <?php endif; ?>
             </span>
-            <br />
         <?php endif; ?>
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-            <span class="price incl tax">
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
+            <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                <?php else: ?>
                     <span class="cart price">
                 <?php endif; ?>
-                <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    </span>
+
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
+                <?php else: ?>
+                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
                 <?php endif; ?>
-            <?php endif; ?>
-            <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <span class="cart tax total"
-                      data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-            <?php else: ?>
-                <span class="cart price">
-            <?php endif; ?>
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
-            <?php else: ?>
-                <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
-            <?php endif; ?>
-            </span>
+                    </span>
 
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                <span class="cart tax info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"
-                      style="display:none;">
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+                    <span class="cart-tax-info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"
+                          style="display: none;">
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <small>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?>
-                        <?php endforeach; ?>
-                    </small>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                    <?php endforeach; ?>
                 <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                     <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                        <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
                     <?php endforeach; ?>
                 <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <small>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?>
-                        <?php endforeach; ?>
-                    </small>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
                 <?php endif; ?>
-            </span>
+                    </span>
 
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <span class="cart tax total"
-                      data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                    <?php echo __('Total incl. tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
-                </span>
-            <?php endif; ?>
-            <?php endif; ?>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?></span>
+                    </span>
+                    <?php endif; ?>
+                <?php endif; ?>
             </span>
         <?php endif; ?>
     </td>
-    <td class="col qty">
-        <span class="qty summary">
+    <td class="col qty" data-th="<?php echo $this->escapeHtml(__('Qty')); ?>">
+        <ul class="items-qty">
             <?php if ($this->getItem()->getQtyOrdered() > 0): ?>
-                <?php echo __('Ordered'); ?>: <strong><?php echo $this->getItem()->getQtyOrdered()*1 ?></strong><br />
+                <li class="item">
+                    <span class="title"><?php echo __('Ordered'); ?></span>
+                    <span class="content"><?php echo $this->getItem()->getQtyOrdered()*1 ?></span>
+                </li>
             <?php endif; ?>
             <?php if ($this->getItem()->getQtyShipped() > 0): ?>
-                <?php echo __('Shipped'); ?>: <strong><?php echo $this->getItem()->getQtyShipped()*1 ?></strong><br />
+                <li class="item">
+                    <span class="title"><?php echo __('Shipped'); ?></span>
+                    <span class="content"><?php echo $this->getItem()->getQtyShipped() * 1 ?></span>
+                </li>
             <?php endif; ?>
             <?php if ($this->getItem()->getQtyCanceled() > 0): ?>
-                <?php echo __('Canceled'); ?>: <strong><?php echo $this->getItem()->getQtyCanceled()*1 ?></strong><br />
+                <li class="item">
+                    <span class="title"><?php echo __('Canceled'); ?></span>
+                    <span class="content"><?php echo $this->getItem()->getQtyCanceled()*1 ?></span>
+                </li>
             <?php endif; ?>
             <?php if ($this->getItem()->getQtyRefunded() > 0): ?>
-                <?php echo __('Refunded'); ?>: <strong><?php echo $this->getItem()->getQtyRefunded()*1 ?></strong><br />
+                <li class="item">
+                    <span class="title"><?php echo __('Refunded'); ?></span>
+                    <span class="content"><?php echo $this->getItem()->getQtyRefunded()*1 ?></span>
+                </li>
             <?php endif; ?>
-        </span>
+        </ul>
     </td>
-    <td class="col subtotal">
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-        <span class="price excl tax">
-            <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart price">
-                <?php endif; ?>
-                <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    </span>
-                <?php endif; ?>
-            <?php endif; ?>
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-            <span class="cart tax total"
-                  data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-            <?php else: ?>
-                <span class="cart price">
-            <?php endif; ?>
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
-                    <?php else: ?>
-                        <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
-                    <?php endif; ?>
-                </span>
-
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                <span class="cart tax info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"
-                      style="display:none;">
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?>
-                            <?php endforeach; ?>
-                        </small>
-                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                            <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></small>
-                        <?php endforeach; ?>
-                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?>
-                            <?php endforeach; ?>
-                        </small>
-                    <?php endif; ?>
-                </span>
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart tax total"
-                          data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                        <?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
-                    </span>
-                <?php endif; ?>
-            <?php endif; ?>
-        </span>
-        <br />
-        <?php endif; ?>
+    <td class="col subtotal" data-th="<?php echo $this->escapeHtml(__('Subtotal')); ?>">
         <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-            <span class="price incl tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart price">
-                    <?php endif; ?>
-                    <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
-            <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($this->getItem()); ?>
-            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                <span class="cart tax total"
-                      data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+            <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
+                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($this->getItem()); ?>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
                 <?php else: ?>
-                <span class="cart price">
+                    <span class="cart price">
                 <?php endif; ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                     <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?>
                 <?php else: ?>
                     <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxRowDisposition()) ?>
                 <?php endif; ?>
-                </span>
+                    </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-                    <span class="cart tax info"
+                    <span class="cart-tax-info"
                           id="subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"
-                          style="display:none;">
+                          style="display: none;">
                         <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?>
-                                <?php endforeach; ?>
-                            </small>
+                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                            <?php endforeach; ?>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></small>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                    <?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?>
-                                <?php endforeach; ?>
-                            </small>
+                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                            <?php endforeach; ?>
                         <?php endif; ?>
                     </span>
 
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart tax total"
+                        <span class="cart-tax-total"
                               data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                            <?php echo __('Total incl. tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?>
+                            <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?></span>
                         </span>
                     <?php endif; ?>
                 <?php endif; ?>
             </span>
         <?php endif; ?>
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
+            <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <span class="cart-tax-total"
+                      data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+            <?php else: ?>
+                <span class="cart price">
+            <?php endif; ?>
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
+            <?php else: ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
+            <?php endif; ?>
+                </span>
+
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+                <span class="cart-tax-info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"
+                      style="display: none;">
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                    <?php endforeach; ?>
+                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
+                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
+                <?php endif; ?>
+                </span>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <span class="cart-tax-total"
+                          data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?></span>
+                    </span>
+                <?php endif; ?>
+            <?php endif; ?>
+        </span>
+        <?php endif; ?>
     </td>
     <?php /*
         <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
diff --git a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php
index 11ea1a7832db51028504ad60d2c5c77f477c2d29..d529aec6484a2a551955ae5f651cbf2afb62f6f8 100644
--- a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php
+++ b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php
@@ -59,13 +59,6 @@ abstract class AbstractEntity extends \Magento\Framework\Model\Resource\Abstract
      */
     protected $_type;
 
-    /**
-     * Attributes array by attribute id
-     *
-     * @var array
-     */
-    protected $_attributesById = array();
-
     /**
      * Attributes array by attribute name
      *
@@ -395,7 +388,6 @@ abstract class AbstractEntity extends \Magento\Framework\Model\Resource\Abstract
     {
         if ($attributes === null) {
             $this->_attributesByCode = array();
-            $this->_attributesById = array();
             $this->_attributesByTable = array();
             return $this;
         }
@@ -414,7 +406,6 @@ abstract class AbstractEntity extends \Magento\Framework\Model\Resource\Abstract
             }
 
             $attr = $this->getAttribute($attrCode);
-            unset($this->_attributesById[$attr->getId()]);
             unset($this->_attributesByTable[$attr->getBackend()->getTable()][$attrCode]);
             unset($this->_attributesByCode[$attrCode]);
         }
@@ -448,20 +439,12 @@ abstract class AbstractEntity extends \Magento\Framework\Model\Resource\Abstract
         $config = $this->_getConfig();
         if (is_numeric($attribute)) {
             $attributeId = $attribute;
-
-            if (isset($this->_attributesById[$attributeId])) {
-                return $this->_attributesById[$attributeId];
-            }
             $attributeInstance = $config->getAttribute($this->getEntityType(), $attributeId);
             if ($attributeInstance) {
                 $attributeCode = $attributeInstance->getAttributeCode();
             }
         } elseif (is_string($attribute)) {
             $attributeCode = $attribute;
-
-            if (isset($this->_attributesByCode[$attributeCode])) {
-                return $this->_attributesByCode[$attributeCode];
-            }
             $attributeInstance = $config->getAttribute($this->getEntityType(), $attributeCode);
             if (!$attributeInstance->getAttributeCode() && in_array($attribute, $this->getDefaultAttributes())) {
                 $attributeInstance->setAttributeCode(
@@ -481,9 +464,6 @@ abstract class AbstractEntity extends \Magento\Framework\Model\Resource\Abstract
         } elseif ($attribute instanceof AbstractAttribute) {
             $attributeInstance = $attribute;
             $attributeCode = $attributeInstance->getAttributeCode();
-            if (isset($this->_attributesByCode[$attributeCode])) {
-                return $this->_attributesByCode[$attributeCode];
-            }
         }
 
         if (empty($attributeInstance)
@@ -553,7 +533,6 @@ abstract class AbstractEntity extends \Magento\Framework\Model\Resource\Abstract
         if ($attribute->isStatic()) {
             $this->_staticAttributes[$attributeCode] = $attribute;
         } else {
-            $this->_attributesById[$attribute->getId()] = $attribute;
             $this->_attributesByTable[$attribute->getBackendTable()][$attributeCode] = $attribute;
         }
 
@@ -798,16 +777,6 @@ abstract class AbstractEntity extends \Magento\Framework\Model\Resource\Abstract
         return $this->_attributesByCode;
     }
 
-    /**
-     * Get attributes by id array
-     *
-     * @return array
-     */
-    public function getAttributesById()
-    {
-        return $this->_attributesById;
-    }
-
     /**
      * Get attributes by table and name array
      *
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
index d83511426262381fb7273f003e60fa58c2ac18be..c289d5d71e25340cf001c527dab0e27383231df0 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
@@ -643,7 +643,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractModel
     {
         // If source model exists - get definition from it
         if ($this->usesSource() && $this->getBackendType() != self::TYPE_STATIC) {
-            return $this->getSource()->getFlatColums();
+            return $this->getSource()->getFlatColumns();
         }
         return $this->_getFlatColumnsDdlDefinition();
     }
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php
index 58409bed4002ef969595b470ae3d737d3d8c46f5..8a638ffef270ab9065a5c714f24061edb585534e 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php
@@ -123,7 +123,7 @@ abstract class AbstractSource implements
      *
      * @return array
      */
-    public function getFlatColums()
+    public function getFlatColumns()
     {
         return array();
     }
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/Boolean.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/Boolean.php
index d46f352430cfee9db95369a3204b664d180c7fb3..78d9b2121e8ee1d53c97b6b469535a477a1d6445 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/Boolean.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/Boolean.php
@@ -108,16 +108,21 @@ class Boolean extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
      *
      * @return array
      */
-    public function getFlatColums()
+    public function getFlatColumns()
     {
         $attributeCode = $this->getAttribute()->getAttributeCode();
-        $column = array('unsigned' => false, 'default' => null, 'extra' => null);
-        $column['type'] = \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT;
-        $column['length'] = 1;
-        $column['nullable'] = true;
-        $column['comment'] = $attributeCode . ' column';
 
-        return array($attributeCode => $column);
+        return [
+            $attributeCode => [
+                'unsigned' => false,
+                'default' => null,
+                'extra' => null,
+                'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
+                'length' => 1,
+                'nullable' => true,
+                'comment' => $attributeCode . ' column',
+            ],
+        ];
     }
 
     /**
@@ -163,4 +168,58 @@ class Boolean extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
 
         return parent::getIndexOptionText($value);
     }
+
+    /**
+     * Add Value Sort To Collection Select
+     *
+     * @param \Magento\Eav\Model\Entity\Collection\AbstractCollection $collection
+     * @param string $dir
+     *
+     * @return \Magento\Eav\Model\Entity\Attribute\Source\Boolean
+     */
+    public function addValueSortToCollection($collection, $dir = \Magento\Framework\DB\Select::SQL_ASC)
+    {
+        $attributeCode = $this->getAttribute()->getAttributeCode();
+        $attributeId = $this->getAttribute()->getId();
+        $attributeTable = $this->getAttribute()->getBackend()->getTable();
+
+        if ($this->getAttribute()->isScopeGlobal()) {
+            $tableName = $attributeCode . '_t';
+            $collection->getSelect()
+                ->joinLeft(
+                    array($tableName => $attributeTable),
+                    "e.entity_id={$tableName}.entity_id"
+                    . " AND {$tableName}.attribute_id='{$attributeId}'"
+                    . " AND {$tableName}.store_id='0'",
+                    array()
+                );
+            $valueExpr = $tableName . '.value';
+        } else {
+            $valueTable1 = $attributeCode . '_t1';
+            $valueTable2 = $attributeCode . '_t2';
+            $collection->getSelect()
+                ->joinLeft(
+                    array($valueTable1 => $attributeTable),
+                    "e.entity_id={$valueTable1}.entity_id"
+                    . " AND {$valueTable1}.attribute_id='{$attributeId}'"
+                    . " AND {$valueTable1}.store_id='0'",
+                    array()
+                )
+                ->joinLeft(
+                    array($valueTable2 => $attributeTable),
+                    "e.entity_id={$valueTable2}.entity_id"
+                    . " AND {$valueTable2}.attribute_id='{$attributeId}'"
+                    . " AND {$valueTable2}.store_id='{$collection->getStoreId()}'",
+                    array()
+                );
+            $valueExpr = $collection->getConnection()->getCheckSql(
+                $valueTable2 . '.value_id > 0',
+                $valueTable2 . '.value',
+                $valueTable1 . '.value'
+            );
+        }
+
+        $collection->getSelect()->order($valueExpr . ' ' . $dir);
+        return $this;
+    }
 }
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php
index 79e2d56f18cd3d0a3cc0e724bbca9078b9ebcbf8..b159e60b695de34eb1f9e000a7c1a33026535ed9 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php
@@ -180,7 +180,7 @@ class Table extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
      *
      * @return array
      */
-    public function getFlatColums()
+    public function getFlatColumns()
     {
         $columns = array();
         $attributeCode = $this->getAttribute()->getAttributeCode();
diff --git a/app/code/Magento/Fedex/Model/Carrier.php b/app/code/Magento/Fedex/Model/Carrier.php
index 8582336c63588e22be78146d49a16898ca2b1462..10a02701ac657da41c907c52bc4c4ae965b49f03 100644
--- a/app/code/Magento/Fedex/Model/Carrier.php
+++ b/app/code/Magento/Fedex/Model/Carrier.php
@@ -414,7 +414,10 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
                 'PackageDetail' => 'INDIVIDUAL_PACKAGES',
                 'RequestedPackageLineItems' => array(
                     '0' => array(
-                        'Weight' => array('Value' => (double)$r->getWeight(), 'Units' => 'LB'),
+                        'Weight' => [
+                            'Value' => (double)$r->getWeight(),
+                            'Units' => $this->getConfigData('unit_of_measure')
+                        ],
                         'GroupPackageCount' => 1
                     )
                 )
@@ -509,7 +512,12 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
 
         if (is_object($response)) {
             if ($response->HighestSeverity == 'FAILURE' || $response->HighestSeverity == 'ERROR') {
-                $errorTitle = (string)$response->Notifications->Message;
+                if (is_array($response->Notifications)) {
+                    $notification = array_pop($response->Notifications);
+                    $errorTitle = (string)$notification->Message;
+                } else {
+                    $errorTitle = (string)$response->Notifications->Message;
+                }
             } elseif (isset($response->RateReplyDetails)) {
                 $allowedMethods = explode(",", $this->getConfigData('allowed_methods'));
 
@@ -916,7 +924,11 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
                 'ADULT' => __('Adult'),
                 'DIRECT' => __('Direct'),
                 'INDIRECT' => __('Indirect')
-            )
+            ),
+            'unit_of_measure' => array(
+                'LB'   =>  __('Pounds'),
+                'KG'   =>  __('Kilograms'),
+            ),
         );
 
         if (!isset($codes[$type])) {
diff --git a/app/code/Magento/Fedex/Model/Source/Unitofmeasure.php b/app/code/Magento/Fedex/Model/Source/Unitofmeasure.php
new file mode 100644
index 0000000000000000000000000000000000000000..227c35619152e67e49768dacbcccd2d3c8a67e8a
--- /dev/null
+++ b/app/code/Magento/Fedex/Model/Source/Unitofmeasure.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+ 
+namespace Magento\Fedex\Model\Source;
+
+class Unitofmeasure extends Generic
+{
+    /**
+     * Carrier code
+     *
+     * @var string
+     */
+    protected $_code = 'unit_of_measure';
+}
diff --git a/app/code/Magento/Fedex/etc/adminhtml/system.xml b/app/code/Magento/Fedex/etc/adminhtml/system.xml
index c718b28fad57e886abba7e50421ee657787545b0..bac1cfe664e523e7446b196fdfaa9cd092b6929a 100644
--- a/app/code/Magento/Fedex/etc/adminhtml/system.xml
+++ b/app/code/Magento/Fedex/etc/adminhtml/system.xml
@@ -80,6 +80,10 @@
                     <label>Dropoff</label>
                     <source_model>Magento\Fedex\Model\Source\Dropoff</source_model>
                 </field>
+                <field id="unit_of_measure" translate="label" type="select" sortOrder="135" showInDefault="1" showInWebsite="1" showInStore="0">
+                    <label>Weight Unit</label>
+                    <source_model>Magento\Fedex\Model\Source\Unitofmeasure</source_model>
+                </field>
                 <field id="max_package_weight" translate="label" type="text" sortOrder="140" showInDefault="1" showInWebsite="1" showInStore="0">
                     <label>Maximum Package Weight (Please consult your shipping carrier for maximum supported shipping weight)</label>
                     <validate>validate-number validate-zero-or-greater</validate>
diff --git a/app/code/Magento/Fedex/etc/config.xml b/app/code/Magento/Fedex/etc/config.xml
index a8ceb55fc54c716aec3508166b308588b3e376c3..04ac4ac73ecb293fb7b22c6f36080c432c38f256 100644
--- a/app/code/Magento/Fedex/etc/config.xml
+++ b/app/code/Magento/Fedex/etc/config.xml
@@ -46,6 +46,7 @@
                 <packaging>YOUR_PACKAGING</packaging>
                 <title>Federal Express</title>
                 <specificerrmsg>This shipping method is currently unavailable. If you would like to ship using this shipping method, please contact us.</specificerrmsg>
+                <unit_of_measure>LB</unit_of_measure>
                 <max_package_weight>150</max_package_weight>
                 <handling_type>F</handling_type>
                 <handling_action>O</handling_action>
diff --git a/app/code/Magento/GiftMessage/Block/Message/Inline.php b/app/code/Magento/GiftMessage/Block/Message/Inline.php
index 988d4a170a949c89d4b41084cef373d5d94ad012..0c4632143976760918191b1980876099c687fb86 100644
--- a/app/code/Magento/GiftMessage/Block/Message/Inline.php
+++ b/app/code/Magento/GiftMessage/Block/Message/Inline.php
@@ -74,6 +74,13 @@ class Inline extends \Magento\Framework\View\Element\Template
      */
     protected $httpContext;
 
+    /**
+     * Checkout type. 'onepage_checkout' and 'multishipping_address' are standard types
+     *
+     * @var string
+     */
+    protected $checkoutType;
+
     /**
      * @param \Magento\Framework\View\Element\Template\Context $context
      * @param \Magento\Customer\Model\Session $customerSession
@@ -142,6 +149,28 @@ class Inline extends \Magento\Framework\View\Element\Template
         return $this->_type;
     }
 
+    /**
+     * Define checkout type
+     *
+     * @param $type string
+     * @return $this
+     */
+    public function setCheckoutType($type)
+    {
+        $this->checkoutType = $type;
+        return $this;
+    }
+
+    /**
+     * Return checkout type. Typical values are 'onepage_checkout' and 'multishipping_address'
+     *
+     * @return string|null
+     */
+    public function getCheckoutType()
+    {
+        return $this->checkoutType;
+    }
+
     /**
      * Check if entity has gift message
      *
diff --git a/app/code/Magento/GiftMessage/Helper/Message.php b/app/code/Magento/GiftMessage/Helper/Message.php
index 2fda8626750f8704e8954c9b51afbcaeb333c109..89f72ee85a9148e19a76703b23ebc69c6d2429c2 100644
--- a/app/code/Magento/GiftMessage/Helper/Message.php
+++ b/app/code/Magento/GiftMessage/Helper/Message.php
@@ -135,7 +135,7 @@ class Message extends \Magento\Core\Helper\Data
             ->setId('giftmessage_form_' . $this->_nextId++)
             ->setDontDisplayContainer($dontDisplayContainer)
             ->setEntity($entity)
-            ->setType($type)->toHtml();
+            ->setCheckoutType($type)->toHtml();
     }
 
     /**
diff --git a/app/code/Magento/GiftMessage/Model/Observer.php b/app/code/Magento/GiftMessage/Model/Observer.php
index 74e695535a76ab5c73bbeb9e473a7cd5b8fbee25..f8d4830fa280a664a030b742221c7b4d0c080bb5 100644
--- a/app/code/Magento/GiftMessage/Model/Observer.php
+++ b/app/code/Magento/GiftMessage/Model/Observer.php
@@ -93,12 +93,14 @@ class Observer extends \Magento\Framework\Object
         $giftMessages = $observer->getEvent()->getRequest()->getParam('giftmessage');
         $quote = $observer->getEvent()->getQuote();
         /* @var $quote \Magento\Sales\Model\Quote */
-        if (is_array($giftMessages)) {
-            foreach ($giftMessages as $entityId => $message) {
-
+        if (!is_array($giftMessages)) {
+            return $this;
+        }
+        // types are 'quote', 'quote_item', etc
+        foreach ($giftMessages as $type => $giftMessageEntities) {
+            foreach ($giftMessageEntities as $entityId => $message) {
                 $giftMessage = $this->_messageFactory->create();
-
-                switch ($message['type']) {
+                switch ($type) {
                     case 'quote':
                         $entity = $quote;
                         break;
diff --git a/app/code/Magento/GiftMessage/Model/Save.php b/app/code/Magento/GiftMessage/Model/Save.php
index f4755a70c55f2ae0a91f3934885a43a3ad0e181f..af93ab1fa55d6b90bcf7409ba69f83f39acac5c2 100644
--- a/app/code/Magento/GiftMessage/Model/Save.php
+++ b/app/code/Magento/GiftMessage/Model/Save.php
@@ -89,7 +89,7 @@ class Save extends \Magento\Framework\Object
         }
 
         foreach ($giftmessages as $entityId => $giftmessage) {
-            $this->_saveOne($entityId, $giftmessage);
+            $this->_saveOne($entityId, $giftmessage, 'quote');
         }
 
         return $this;
@@ -108,14 +108,17 @@ class Save extends \Magento\Framework\Object
      */
     public function saveAllInOrder()
     {
-        $giftmessages = $this->getGiftmessages();
+        $giftMessages = $this->getGiftmessages();
 
-        if (!is_array($giftmessages)) {
+        if (!is_array($giftMessages)) {
             return $this;
         }
 
-        foreach ($giftmessages as $entityId => $giftmessage) {
-            $this->_saveOne($entityId, $giftmessage);
+        // types are 'quote', 'quote_item', etc
+        foreach ($giftMessages as $type => $giftMessageEntities) {
+            foreach ($giftMessageEntities as $entityId => $giftmessage) {
+                $this->_saveOne($entityId, $giftmessage, $type);
+            }
         }
 
         return $this;
@@ -126,13 +129,13 @@ class Save extends \Magento\Framework\Object
      *
      * @param int $entityId
      * @param array $giftmessage
+     * @param string $entityType
      * @return $this
      */
-    protected function _saveOne($entityId, $giftmessage)
+    protected function _saveOne($entityId, $giftmessage, $entityType)
     {
         /* @var $giftmessageModel \Magento\GiftMessage\Model\Message */
         $giftmessageModel = $this->_messageFactory->create();
-        $entityType = $this->_getMappedType($giftmessage['type']);
 
         switch ($entityType) {
             case 'quote':
@@ -343,23 +346,6 @@ class Save extends \Magento\Framework\Object
         return $this;
     }
 
-    /**
-     * Retrieve mapped type for entity
-     *
-     * @param string $type
-     * @return string|null
-     */
-    protected function _getMappedType($type)
-    {
-        $map = array('main' => 'quote', 'item' => 'quote_item', 'order' => 'order', 'order_item' => 'order_item');
-
-        if (isset($map[$type])) {
-            return $map[$type];
-        }
-
-        return null;
-    }
-
     /**
      * Retrieve quote object
      *
diff --git a/app/code/Magento/GiftMessage/view/frontend/templates/inline.phtml b/app/code/Magento/GiftMessage/view/frontend/templates/inline.phtml
index 42e7020c4666bf3fa8ee464ba746a06a0a052349..a313569ac833bf95804e3467b4867ff9bf87fa78 100644
--- a/app/code/Magento/GiftMessage/view/frontend/templates/inline.phtml
+++ b/app/code/Magento/GiftMessage/view/frontend/templates/inline.phtml
@@ -29,7 +29,7 @@
 </script>
 <?php endif ?>
 
-<?php switch ($this->getType()): ?>
+<?php switch ($this->getCheckoutType()): ?>
 <?php case 'onepage_checkout': ?>
     <fieldset class="fieldset gift-message">
         <legend class="legend"><span><?php echo __('Do you have any gift items in your order?'); ?></span></legend><br>
@@ -50,28 +50,26 @@
 
             <dd id="allow-gift-options-for-order-container" class="order-options">
                 <div class="options-order-container" id="options-order-container-<?php echo $this->getEntity()->getId() ?>"></div>
-                <input type="hidden" name="giftoptions[<?php echo $this->getEntity()->getId() ?>][type]" value="quote" />
                     <a href="#" class="action activate message" data-mage-init='{"toggleAdvanced": {"selectorsToggleClass":"hidden", "toggleContainers":"#allow-gift-messages-for-order-container"}}'><?php echo __('Gift Message') ?></a>
                     <div id="allow-gift-messages-for-order-container" class="gift-messages-order hidden">
                         <fieldset class="fieldset">
-                            <input type="hidden" name="giftmessage[<?php echo $this->getEntity()->getId() ?>][type]"  value="quote" />
                             <p><?php echo __('If you don\'t want to leave a gift message for the entire order, leave this box blank.') ?></p>
                             <div class="field from">
                                 <label for="gift-message-whole-from" class="label"><span><?php echo __('From') ?></span></label>
                                 <div class="control">
-                                    <input type="text" name="giftmessage[<?php echo $this->getEntity()->getId() ?>][from]" id="gift-message-whole-from" title="<?php echo __('From') ?>"  value="<?php echo $this->getEscaped($this->getMessage()->getSender(), $this->getDefaultFrom()) ?>" class="input-text">
+                                    <input type="text" name="giftmessage[quote][<?php echo $this->getEntity()->getId() ?>][from]" id="gift-message-whole-from" title="<?php echo __('From') ?>"  value="<?php echo $this->getEscaped($this->getMessage()->getSender(), $this->getDefaultFrom()) ?>" class="input-text">
                                 </div>
                             </div>
                             <div class="field to">
                                 <label for="gift-message-whole-to" class="label"><span><?php echo __('To') ?></span></label>
                                 <div class="control">
-                                    <input type="text" name="giftmessage[<?php echo $this->getEntity()->getId() ?>][to]" id="gift-message-whole-to" title="<?php echo __('To') ?>" value="<?php echo $this->getEscaped($this->getMessage()->getRecipient(), $this->getDefaultTo()) ?>" class="input-text">
+                                    <input type="text" name="giftmessage[quote][<?php echo $this->getEntity()->getId() ?>][to]" id="gift-message-whole-to" title="<?php echo __('To') ?>" value="<?php echo $this->getEscaped($this->getMessage()->getRecipient(), $this->getDefaultTo()) ?>" class="input-text">
                                 </div>
                             </div>
                             <div class="field text">
                                 <label for="gift-message-whole-message" class="label"><span><?php echo __('Message') ?></span></label>
                                 <div class="control">
-                                    <textarea id="gift-message-whole-message" class="input-text" name="giftmessage[<?php echo $this->getEntity()->getId() ?>][message]" title="<?php echo __('Message') ?>" rows="5" cols="10"><?php echo $this->getEscaped($this->getMessage()->getMessage()) ?></textarea>
+                                    <textarea id="gift-message-whole-message" class="input-text" name="giftmessage[quote][<?php echo $this->getEntity()->getId() ?>][message]" title="<?php echo __('Message') ?>" rows="5" cols="10"><?php echo $this->getEscaped($this->getMessage()->getMessage()) ?></textarea>
                                 </div>
                             </div>
                         </fieldset>
@@ -95,7 +93,6 @@
                     <?php foreach($this->getItems() as $_index=>$_item): ?>
                     <?php $_product=$_item->getProduct() ?>
                     <li class="item">
-                         <input type="hidden" name="giftoptions[<?php echo $_item->getId() ?>][type]" value="quote_item" />
                          <div class="product">
                              <div class="number">
                                  <?php echo __('<span>Item %1</span> of %2', $_index+1, $this->countItems()) ?>
@@ -113,23 +110,22 @@
                              <div id="gift-messages-for-item-container-<?php echo $_item->getId() ?>" class="block message hidden">
                                  <fieldset class="fieldset">
                                      <p><?php echo __('You can leave a box blank if you don\'t wish to add a gift message for the item.') ?></p>
-                                     <input type="hidden" name="giftmessage[<?php echo $_item->getId() ?>][type]" value="quote_item" >
                                      <div class="field from">
                                          <label for="gift-message-<?php echo $_item->getId() ?>-from" class="label"><span><?php echo __('From') ?></span></label>
                                          <div class="control">
-                                             <input type="text" name="giftmessage[<?php echo $_item->getId() ?>][from]" id="gift-message-<?php echo $_item->getId() ?>-from" title="<?php echo __('From') ?>" value="<?php echo $this->getEscaped($this->getMessage($_item)->getSender(), $this->getDefaultFrom()) ?>" class="input-text">
+                                             <input type="text" name="giftmessage[quote_item][<?php echo $_item->getId() ?>][from]" id="gift-message-<?php echo $_item->getId() ?>-from" title="<?php echo __('From') ?>" value="<?php echo $this->getEscaped($this->getMessage($_item)->getSender(), $this->getDefaultFrom()) ?>" class="input-text">
                                          </div>
                                      </div>
                                      <div class="field to">
                                         <label for="gift-message-<?php echo $_item->getId() ?>-to" class="label"><span><?php echo __('To') ?></span></label>
                                         <div class="control">
-                                            <input type="text" name="giftmessage[<?php echo $_item->getId() ?>][to]" id="gift-message-<?php echo $_item->getId() ?>-to" title="<?php echo __('To') ?>" value="<?php echo $this->getEscaped($this->getMessage($_item)->getRecipient(), $this->getDefaultTo()) ?>" class="input-text">
+                                            <input type="text" name="giftmessage[quote_item][<?php echo $_item->getId() ?>][to]" id="gift-message-<?php echo $_item->getId() ?>-to" title="<?php echo __('To') ?>" value="<?php echo $this->getEscaped($this->getMessage($_item)->getRecipient(), $this->getDefaultTo()) ?>" class="input-text">
                                         </div>
                                      </div>
                                      <div class="field text">
                                          <label for="gift-message-<?php echo $_item->getId() ?>-message" class="label"><span><?php echo __('Message') ?></span></label>
                                          <div class="control">
-                                            <textarea id="gift-message-<?php echo $_item->getId() ?>-message" class="input-text giftmessage-area" name="giftmessage[<?php echo $_item->getId() ?>][message]" title="<?php echo __('Message') ?>" rows="5" cols="40"><?php echo $this->getEscaped($this->getMessage($_item)->getMessage()) ?></textarea>
+                                            <textarea id="gift-message-<?php echo $_item->getId() ?>-message" class="input-text giftmessage-area" name="giftmessage[quote_item][<?php echo $_item->getId() ?>][message]" title="<?php echo __('Message') ?>" rows="5" cols="40"><?php echo $this->getEscaped($this->getMessage($_item)->getMessage()) ?></textarea>
                                          </div>
                                      </div>
                                 </fieldset>
@@ -173,30 +169,28 @@
 
             <dd id="allow-gift-options-for-order-container-<?php echo $this->getEntity()->getId() ?>" class="order-options">
                 <div class="options-order-container" id="options-order-container-<?php echo $this->getEntity()->getId() ?>"></div>
-                <input type="hidden" name="giftoptions[<?php echo $this->getEntity()->getId() ?>][type]" value="quote_address" />
                 <?php if ($this->isMessagesAvailable()): ?>
                     <?php $_giftMessage = true; ?>
                     <a href="#" class="action activate message" data-mage-init='{"toggleAdvanced": {"selectorsToggleClass":"hidden", "toggleContainers":"#gift-messages-for-order-container-<?php echo $this->getEntity()->getId() ?>"}}'><?php echo __('Gift Message') ?></a>
                     <div id="gift-messages-for-order-container-<?php echo $this->getEntity()->getId() ?>" class="block message hidden">
                         <fieldset class="fieldset">
                             <p><?php echo __('You can leave this box blank if you do not wish to add a gift message for this address.') ?></p>
-                            <input type="hidden" name="giftmessage[<?php echo $this->getEntity()->getId() ?>][type]" value="quote_address" />
                             <div class="field from">
                                 <label for="gift-message-<?php echo $this->getEntity()->getId() ?>-from" class="label"><span><?php echo __('From') ?></span></label>
                                 <div class="control">
-                                    <input type="text" name="giftmessage[<?php echo $this->getEntity()->getId() ?>][from]" id="gift-message-<?php echo $this->getEntity()->getId() ?>-from" title="<?php echo __('From') ?>" value="<?php echo $this->getEscaped($this->getMessage()->getSender(), $this->getDefaultFrom()) ?>" class="input-text">
+                                    <input type="text" name="giftmessage[quote_address][<?php echo $this->getEntity()->getId() ?>][from]" id="gift-message-<?php echo $this->getEntity()->getId() ?>-from" title="<?php echo __('From') ?>" value="<?php echo $this->getEscaped($this->getMessage()->getSender(), $this->getDefaultFrom()) ?>" class="input-text">
                                 </div>
                             </div>
                             <div class="field to">
                                 <label for="gift-message-<?php echo $this->getEntity()->getId() ?>-to" class="label"><span><?php echo __('To') ?></span></label>
                                 <div class="control">
-                                    <input type="text" name="giftmessage[<?php echo $this->getEntity()->getId() ?>][to]" id="gift-message-<?php echo $this->getEntity()->getId() ?>-to" title="<?php echo __('To') ?>" value="<?php echo $this->getEscaped($this->getMessage()->getRecipient(), $this->getDefaultTo()) ?>" class="input-text">
+                                    <input type="text" name="giftmessage[quote_address][<?php echo $this->getEntity()->getId() ?>][to]" id="gift-message-<?php echo $this->getEntity()->getId() ?>-to" title="<?php echo __('To') ?>" value="<?php echo $this->getEscaped($this->getMessage()->getRecipient(), $this->getDefaultTo()) ?>" class="input-text">
                                 </div>
                             </div>
                             <div class="field text">
                                 <label for="gift-message-<?php echo $this->getEntity()->getId() ?>-message" class="label"><span><?php echo __('Message') ?></span></label>
                                 <div class="control">
-                                    <textarea id="gift-message-<?php echo $this->getEntity()->getId() ?>-message" class="input-text" name="giftmessage[<?php echo $this->getEntity()->getId() ?>][message]" title="<?php echo __('Message') ?>" rows="5" cols="40"><?php echo $this->getEscaped($this->getMessage()->getMessage()) ?></textarea>
+                                    <textarea id="gift-message-<?php echo $this->getEntity()->getId() ?>-message" class="input-text" name="giftmessage[quote_address][<?php echo $this->getEntity()->getId() ?>][message]" title="<?php echo __('Message') ?>" rows="5" cols="40"><?php echo $this->getEscaped($this->getMessage()->getMessage()) ?></textarea>
                                 </div>
                             </div>
                         </fieldset>
@@ -228,8 +222,7 @@
                          </div>
                          <div class="item options">
                              <div class="options-items-container" id="options-items-container-<?php echo $this->getEntity()->getId() ?>-<?php echo $_item->getId() ?>"></div>
-                             <input type="hidden" name="giftoptions[<?php echo $_item->getId() ?>][type]" value="quote_address_item" />
-                             <input type="hidden" name="giftoptions[<?php echo $_item->getId() ?>][address]" value="<?php echo $this->getEntity()->getId()?>" />
+                             <input type="hidden" name="giftoptions[quote_address_item][<?php echo $_item->getId() ?>][address]" value="<?php echo $this->getEntity()->getId()?>" />
 
                              <?php if ($this->isItemMessagesAvailable($_item)): ?>
                              <?php $_giftMessage = true; ?>
@@ -237,24 +230,23 @@
                                  <div id="gift-messages-for-item-container-<?php echo $_item->getId() ?>" class="block message hidden">
                                      <fieldset class="fieldset">
                                         <p><?php echo __('You can leave this box blank if you do not wish to add a gift message for the item.') ?></p>
-                                         <input type="hidden" name="giftmessage[<?php echo $_item->getId() ?>][type]" value="quote_address_item" />
-                                         <input type="hidden" name="giftmessage[<?php echo $_item->getId() ?>][address]" value="<?php echo $this->getEntity()->getId()?>" />
+                                         <input type="hidden" name="giftmessage[quote_address_item][<?php echo $_item->getId() ?>][address]" value="<?php echo $this->getEntity()->getId()?>" />
                                          <div class="field from">
                                              <label for="gift-message-<?php echo $_item->getId() ?>-from" class="label"><span><?php echo __('From') ?></span></label>
                                              <div class="control">
-                                                 <input type="text" name="giftmessage[<?php echo $_item->getId() ?>][from]" id="gift-message-<?php echo $_item->getId() ?>-from" title="<?php echo __('From') ?>"  value="<?php echo $this->getEscaped($this->getMessage($_item)->getSender(), $this->getDefaultFrom()) ?>" class="input-text">
+                                                 <input type="text" name="giftmessage[quote_address_item][<?php echo $_item->getId() ?>][from]" id="gift-message-<?php echo $_item->getId() ?>-from" title="<?php echo __('From') ?>"  value="<?php echo $this->getEscaped($this->getMessage($_item)->getSender(), $this->getDefaultFrom()) ?>" class="input-text">
                                              </div>
                                          </div>
                                          <div class="field to">
                                             <label for="gift-message-<?php echo $_item->getId() ?>-to" class="label"><span><?php echo __('To') ?></span></label>
                                             <div class="control">
-                                                <input type="text" name="giftmessage[<?php echo $_item->getId() ?>][to]" id="gift-message-<?php echo $_item->getId() ?>-to" title="<?php echo __('To') ?>" value="<?php echo $this->getEscaped($this->getMessage($_item)->getRecipient(), $this->getDefaultTo()) ?>" class="input-text">
+                                                <input type="text" name="giftmessage[quote_address_item][<?php echo $_item->getId() ?>][to]" id="gift-message-<?php echo $_item->getId() ?>-to" title="<?php echo __('To') ?>" value="<?php echo $this->getEscaped($this->getMessage($_item)->getRecipient(), $this->getDefaultTo()) ?>" class="input-text">
                                             </div>
                                         </div>
                                          <div class="field text">
                                              <label for="gift-message-<?php echo $_item->getId() ?>-message" class="label"><span><?php echo __('Message') ?></span></label>
                                              <div class="control">
-                                                <textarea id="gift-message-<?php echo $_item->getId() ?>-message" class="input-text giftmessage-area" name="giftmessage[<?php echo $_item->getId() ?>][message]" title="<?php echo __('Message') ?>" rows="5" cols="10"><?php echo $this->getEscaped($this->getMessage($_item)->getMessage()) ?></textarea>
+                                                <textarea id="gift-message-<?php echo $_item->getId() ?>-message" class="input-text giftmessage-area" name="giftmessage[quote_address_item][<?php echo $_item->getId() ?>][message]" title="<?php echo __('Message') ?>" rows="5" cols="10"><?php echo $this->getEscaped($this->getMessage($_item)->getMessage()) ?></textarea>
                                              </div>
                                          </div>
                                      </fieldset>
diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributeSetsAction.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributeSets.php
similarity index 92%
rename from app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributeSetsAction.php
rename to app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributeSets.php
index 45c9a5fed4dc4f897658ef3ecda22b656e749036..0662d2865df6bd0c43f2f2f99cedc7c15e37e01b 100644
--- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributeSetsAction.php
+++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributeSets.php
@@ -24,14 +24,14 @@
  */
 namespace Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\Types;
 
-class LoadAttributeSetsAction extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\Types
+class LoadAttributeSets extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\Types
 {
     /**
      * Get available attribute sets
      *
      * @return void
      */
-    protected function execute()
+    public function execute()
     {
         try {
             $this->getResponse()->setBody(
diff --git a/app/code/Magento/GoogleShopping/Model/Attribute.php b/app/code/Magento/GoogleShopping/Model/Attribute.php
index 04e83ec06952973e094ba9e343a91ca339563aca..39981db43b7f1a3fffd520f682f8b2d44c4acc38 100644
--- a/app/code/Magento/GoogleShopping/Model/Attribute.php
+++ b/app/code/Magento/GoogleShopping/Model/Attribute.php
@@ -67,7 +67,7 @@ class Attribute extends \Magento\Framework\Model\AbstractModel
     /**
      * @var \Magento\GoogleShopping\Helper\Data|null
      */
-    protected $_gsData = null;
+    protected $_googleShoppingHelper = null;
 
     /**
      * @var \Magento\GoogleShopping\Helper\Product|null
@@ -90,7 +90,7 @@ class Attribute extends \Magento\Framework\Model\AbstractModel
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Catalog\Model\ProductFactory $productFactory
-     * @param \Magento\GoogleShopping\Helper\Data $gsData
+     * @param \Magento\GoogleShopping\Helper\Data $googleShoppingHelper
      * @param \Magento\GoogleShopping\Helper\Product $gsProduct
      * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice
      * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource
@@ -101,7 +101,7 @@ class Attribute extends \Magento\Framework\Model\AbstractModel
         \Magento\Framework\Model\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Catalog\Model\ProductFactory $productFactory,
-        \Magento\GoogleShopping\Helper\Data $gsData,
+        \Magento\GoogleShopping\Helper\Data $googleShoppingHelper,
         \Magento\GoogleShopping\Helper\Product $gsProduct,
         \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice,
         \Magento\GoogleShopping\Model\Resource\Attribute $resource,
@@ -109,7 +109,7 @@ class Attribute extends \Magento\Framework\Model\AbstractModel
         array $data = array()
     ) {
         $this->_productFactory = $productFactory;
-        $this->_gsData = $gsData;
+        $this->_googleShoppingHelper = $googleShoppingHelper;
         $this->_gsProduct = $gsProduct;
         $this->catalogPrice = $catalogPrice;
         parent::__construct($context, $registry, $resource, $resourceCollection, $data);
diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/Content.php b/app/code/Magento/GoogleShopping/Model/Attribute/Content.php
index b750290f0f9762b72fcb30a19acfdfdbbcbb0b0e..d1667bbd47f5ee8335de9d261c3b669fc74faf56 100644
--- a/app/code/Magento/GoogleShopping/Model/Attribute/Content.php
+++ b/app/code/Magento/GoogleShopping/Model/Attribute/Content.php
@@ -53,7 +53,7 @@ class Content extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
         } else {
             $descrText = 'no description';
         }
-        $descrText = $this->_gsData->cleanAtomAttribute($descrText);
+        $descrText = $this->_googleShoppingHelper->cleanAtomAttribute($descrText);
         $entry->setContent($entry->getService()->newContent()->setText($descrText));
 
         return $entry;
diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/ContentLanguage.php b/app/code/Magento/GoogleShopping/Model/Attribute/ContentLanguage.php
index 899e8ca3dc4813448e4139a0d34fa4696aed58f3..ced7722ed051a356e4bee98ec7f36eaef57abf87 100644
--- a/app/code/Magento/GoogleShopping/Model/Attribute/ContentLanguage.php
+++ b/app/code/Magento/GoogleShopping/Model/Attribute/ContentLanguage.php
@@ -41,7 +41,7 @@ class ContentLanguage extends \Magento\GoogleShopping\Model\Attribute\DefaultAtt
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Catalog\Model\ProductFactory $productFactory
-     * @param \Magento\GoogleShopping\Helper\Data $gsData
+     * @param \Magento\GoogleShopping\Helper\Data $googleShoppingHelper
      * @param \Magento\GoogleShopping\Helper\Product $gsProduct
      * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice
      * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource
@@ -53,7 +53,7 @@ class ContentLanguage extends \Magento\GoogleShopping\Model\Attribute\DefaultAtt
         \Magento\Framework\Model\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Catalog\Model\ProductFactory $productFactory,
-        \Magento\GoogleShopping\Helper\Data $gsData,
+        \Magento\GoogleShopping\Helper\Data $googleShoppingHelper,
         \Magento\GoogleShopping\Helper\Product $gsProduct,
         \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice,
         \Magento\GoogleShopping\Model\Resource\Attribute $resource,
@@ -66,7 +66,7 @@ class ContentLanguage extends \Magento\GoogleShopping\Model\Attribute\DefaultAtt
             $context,
             $registry,
             $productFactory,
-            $gsData,
+            $googleShoppingHelper,
             $gsProduct,
             $catalogPrice,
             $resource,
diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/Destinations.php b/app/code/Magento/GoogleShopping/Model/Attribute/Destinations.php
index f11012039661b5edc1506a15fe7f31fc91f5c624..a553543885b21582daecea287bed55eae6d5a7fa 100644
--- a/app/code/Magento/GoogleShopping/Model/Attribute/Destinations.php
+++ b/app/code/Magento/GoogleShopping/Model/Attribute/Destinations.php
@@ -41,7 +41,7 @@ class Destinations extends \Magento\GoogleShopping\Model\Attribute\DefaultAttrib
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Catalog\Model\ProductFactory $productFactory
-     * @param \Magento\GoogleShopping\Helper\Data $gsData
+     * @param \Magento\GoogleShopping\Helper\Data $googleShoppingHelper
      * @param \Magento\GoogleShopping\Helper\Product $gsProduct
      * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice
      * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource
@@ -53,7 +53,7 @@ class Destinations extends \Magento\GoogleShopping\Model\Attribute\DefaultAttrib
         \Magento\Framework\Model\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Catalog\Model\ProductFactory $productFactory,
-        \Magento\GoogleShopping\Helper\Data $gsData,
+        \Magento\GoogleShopping\Helper\Data $googleShoppingHelper,
         \Magento\GoogleShopping\Helper\Product $gsProduct,
         \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice,
         \Magento\GoogleShopping\Model\Resource\Attribute $resource,
@@ -66,7 +66,7 @@ class Destinations extends \Magento\GoogleShopping\Model\Attribute\DefaultAttrib
             $context,
             $registry,
             $productFactory,
-            $gsData,
+            $googleShoppingHelper,
             $gsProduct,
             $catalogPrice,
             $resource,
diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/GoogleProductCategory.php b/app/code/Magento/GoogleShopping/Model/Attribute/GoogleProductCategory.php
index 86d2631920a59e3cf7aafb58061765391a6499e1..9034b81b2c68725e88a02fe955094487b4d232be 100644
--- a/app/code/Magento/GoogleShopping/Model/Attribute/GoogleProductCategory.php
+++ b/app/code/Magento/GoogleShopping/Model/Attribute/GoogleProductCategory.php
@@ -48,7 +48,7 @@ class GoogleProductCategory extends \Magento\GoogleShopping\Model\Attribute\Defa
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Catalog\Model\ProductFactory $productFactory
-     * @param \Magento\GoogleShopping\Helper\Data $gsData
+     * @param \Magento\GoogleShopping\Helper\Data $googleShoppingHelper
      * @param \Magento\GoogleShopping\Helper\Product $gsProduct
      * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice
      * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource
@@ -61,7 +61,7 @@ class GoogleProductCategory extends \Magento\GoogleShopping\Model\Attribute\Defa
         \Magento\Framework\Model\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Catalog\Model\ProductFactory $productFactory,
-        \Magento\GoogleShopping\Helper\Data $gsData,
+        \Magento\GoogleShopping\Helper\Data $googleShoppingHelper,
         \Magento\GoogleShopping\Helper\Product $gsProduct,
         \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice,
         \Magento\GoogleShopping\Model\Resource\Attribute $resource,
@@ -76,7 +76,7 @@ class GoogleProductCategory extends \Magento\GoogleShopping\Model\Attribute\Defa
             $context,
             $registry,
             $productFactory,
-            $gsData,
+            $googleShoppingHelper,
             $gsProduct,
             $catalogPrice,
             $resource,
diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/Id.php b/app/code/Magento/GoogleShopping/Model/Attribute/Id.php
index 3115a0cdec9846d38fabb08f212d55dc5dc414a3..781f6b0e2086ad139b86a1715c9e93a54f3e61af 100644
--- a/app/code/Magento/GoogleShopping/Model/Attribute/Id.php
+++ b/app/code/Magento/GoogleShopping/Model/Attribute/Id.php
@@ -40,7 +40,7 @@ class Id extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
      */
     public function convertAttribute($product, $entry)
     {
-        $value = $this->_gsData->buildContentProductId($product->getId(), $product->getStoreId());
+        $value = $this->_googleShoppingHelper->buildContentProductId($product->getId(), $product->getStoreId());
         return $this->_setAttribute($entry, 'id', self::ATTRIBUTE_TYPE_TEXT, $value);
     }
 }
diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/ImageLink.php b/app/code/Magento/GoogleShopping/Model/Attribute/ImageLink.php
index 07c16720f5e4f9e91ef4d53cdbb0a750cd228c13..ece4dc9a56ec7eda7fd678b6deaa4759867f865b 100644
--- a/app/code/Magento/GoogleShopping/Model/Attribute/ImageLink.php
+++ b/app/code/Magento/GoogleShopping/Model/Attribute/ImageLink.php
@@ -39,7 +39,7 @@ class ImageLink extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Catalog\Model\ProductFactory $productFactory
-     * @param \Magento\GoogleShopping\Helper\Data $gsData
+     * @param \Magento\GoogleShopping\Helper\Data $googleShoppingHelper
      * @param \Magento\GoogleShopping\Helper\Product $gsProduct
      * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice
      * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource
@@ -51,7 +51,7 @@ class ImageLink extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
         \Magento\Framework\Model\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Catalog\Model\ProductFactory $productFactory,
-        \Magento\GoogleShopping\Helper\Data $gsData,
+        \Magento\GoogleShopping\Helper\Data $googleShoppingHelper,
         \Magento\GoogleShopping\Helper\Product $gsProduct,
         \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice,
         \Magento\GoogleShopping\Model\Resource\Attribute $resource,
@@ -64,7 +64,7 @@ class ImageLink extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
             $context,
             $registry,
             $productFactory,
-            $gsData,
+            $googleShoppingHelper,
             $gsProduct,
             $catalogPrice,
             $resource,
diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/Link.php b/app/code/Magento/GoogleShopping/Model/Attribute/Link.php
index f2c290a7884468901d9f425bd9740bedbfe3dfd9..3705a74a250d4f0830d4300038e620f729054f9b 100644
--- a/app/code/Magento/GoogleShopping/Model/Attribute/Link.php
+++ b/app/code/Magento/GoogleShopping/Model/Attribute/Link.php
@@ -39,7 +39,7 @@ class Link extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Catalog\Model\ProductFactory $productFactory
-     * @param \Magento\GoogleShopping\Helper\Data $gsData
+     * @param \Magento\GoogleShopping\Helper\Data $googleShoppingHelper
      * @param \Magento\GoogleShopping\Helper\Product $gsProduct
      * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice
      * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource
@@ -51,7 +51,7 @@ class Link extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
         \Magento\Framework\Model\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Catalog\Model\ProductFactory $productFactory,
-        \Magento\GoogleShopping\Helper\Data $gsData,
+        \Magento\GoogleShopping\Helper\Data $googleShoppingHelper,
         \Magento\GoogleShopping\Helper\Product $gsProduct,
         \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice,
         \Magento\GoogleShopping\Model\Resource\Attribute $resource,
@@ -64,7 +64,7 @@ class Link extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
             $context,
             $registry,
             $productFactory,
-            $gsData,
+            $googleShoppingHelper,
             $gsProduct,
             $catalogPrice,
             $resource,
diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/Price.php b/app/code/Magento/GoogleShopping/Model/Attribute/Price.php
index cb8f296c2f378aceafab1c4f7521c245357b7a9a..305eec75a9990971b715de07324e18f95817e409 100644
--- a/app/code/Magento/GoogleShopping/Model/Attribute/Price.php
+++ b/app/code/Magento/GoogleShopping/Model/Attribute/Price.php
@@ -69,7 +69,7 @@ class Price extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Catalog\Model\ProductFactory $productFactory
-     * @param \Magento\GoogleShopping\Helper\Data $gsData
+     * @param \Magento\GoogleShopping\Helper\Data $googleShoppingHelper
      * @param \Magento\GoogleShopping\Helper\Product $gsProduct
      * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice
      * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource
@@ -86,7 +86,7 @@ class Price extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
         \Magento\Framework\Model\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Catalog\Model\ProductFactory $productFactory,
-        \Magento\GoogleShopping\Helper\Data $gsData,
+        \Magento\GoogleShopping\Helper\Data $googleShoppingHelper,
         \Magento\GoogleShopping\Helper\Product $gsProduct,
         \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice,
         \Magento\GoogleShopping\Model\Resource\Attribute $resource,
@@ -106,7 +106,7 @@ class Price extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
             $context,
             $registry,
             $productFactory,
-            $gsData,
+            $googleShoppingHelper,
             $gsProduct,
             $catalogPrice,
             $resource,
diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/ProductType.php b/app/code/Magento/GoogleShopping/Model/Attribute/ProductType.php
index 50ee7841461afe837e957a30488a0dcfe727abf3..0b175b63f22fa5cac4b0023e5ca26133c3de51cd 100644
--- a/app/code/Magento/GoogleShopping/Model/Attribute/ProductType.php
+++ b/app/code/Magento/GoogleShopping/Model/Attribute/ProductType.php
@@ -41,7 +41,7 @@ class ProductType extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribu
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Catalog\Model\ProductFactory $productFactory
-     * @param \Magento\GoogleShopping\Helper\Data $gsData
+     * @param \Magento\GoogleShopping\Helper\Data $googleShoppingHelper
      * @param \Magento\GoogleShopping\Helper\Product $gsProduct
      * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice
      * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource
@@ -53,7 +53,7 @@ class ProductType extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribu
         \Magento\Framework\Model\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Catalog\Model\ProductFactory $productFactory,
-        \Magento\GoogleShopping\Helper\Data $gsData,
+        \Magento\GoogleShopping\Helper\Data $googleShoppingHelper,
         \Magento\GoogleShopping\Helper\Product $gsProduct,
         \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice,
         \Magento\GoogleShopping\Model\Resource\Attribute $resource,
@@ -66,7 +66,7 @@ class ProductType extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribu
             $context,
             $registry,
             $productFactory,
-            $gsData,
+            $googleShoppingHelper,
             $gsProduct,
             $catalogPrice,
             $resource,
diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/TargetCountry.php b/app/code/Magento/GoogleShopping/Model/Attribute/TargetCountry.php
index 9963f95fa5e257b19fc019cd5b381e45b987f0da..82c8e61e9d1d9fb3e71c43465d1609625370a064 100644
--- a/app/code/Magento/GoogleShopping/Model/Attribute/TargetCountry.php
+++ b/app/code/Magento/GoogleShopping/Model/Attribute/TargetCountry.php
@@ -41,7 +41,7 @@ class TargetCountry extends \Magento\GoogleShopping\Model\Attribute\DefaultAttri
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Catalog\Model\ProductFactory $productFactory
-     * @param \Magento\GoogleShopping\Helper\Data $gsData
+     * @param \Magento\GoogleShopping\Helper\Data $googleShoppingHelper
      * @param \Magento\GoogleShopping\Helper\Product $gsProduct
      * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice
      * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource
@@ -53,7 +53,7 @@ class TargetCountry extends \Magento\GoogleShopping\Model\Attribute\DefaultAttri
         \Magento\Framework\Model\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Catalog\Model\ProductFactory $productFactory,
-        \Magento\GoogleShopping\Helper\Data $gsData,
+        \Magento\GoogleShopping\Helper\Data $googleShoppingHelper,
         \Magento\GoogleShopping\Helper\Product $gsProduct,
         \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice,
         \Magento\GoogleShopping\Model\Resource\Attribute $resource,
@@ -66,7 +66,7 @@ class TargetCountry extends \Magento\GoogleShopping\Model\Attribute\DefaultAttri
             $context,
             $registry,
             $productFactory,
-            $gsData,
+            $googleShoppingHelper,
             $gsProduct,
             $catalogPrice,
             $resource,
diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/Tax.php b/app/code/Magento/GoogleShopping/Model/Attribute/Tax.php
index f2e4c0173dd3877504c92050f0fa8a3956094e0d..6a9a1c1251c02bc337746af7a6ea83e1ff292e06 100644
--- a/app/code/Magento/GoogleShopping/Model/Attribute/Tax.php
+++ b/app/code/Magento/GoogleShopping/Model/Attribute/Tax.php
@@ -23,6 +23,10 @@
  */
 namespace Magento\GoogleShopping\Model\Attribute;
 
+use Magento\Store\Model\Store;
+use Magento\Framework\Parse\Zip;
+use Magento\Tax\Service\V1\Data\TaxClassKey;
+
 /**
  * Tax attribute model
  *
@@ -40,11 +44,6 @@ class Tax extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
      */
     protected $_taxData = null;
 
-    /**
-     * @var \Magento\Tax\Model\Calculation
-     */
-    protected $calculation;
-
     /**
      * Config
      *
@@ -52,17 +51,71 @@ class Tax extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
      */
     protected $_config;
 
+    /**
+     * Tax Rule Service
+     *
+     * @var \Magento\Tax\Service\V1\TaxRuleService
+     */
+    protected $_taxRuleService;
+
+    /**
+     * Tax Calculation Service
+     *
+     * @var \Magento\Tax\Service\V1\TaxCalculationService
+     */
+    protected $_taxCalculationService;
+
+    /**
+     * Quote Details Builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\QuoteDetailsBuilder
+     */
+    protected $_quoteDetailsBuilder;
+
+    /**
+     * Quote Details Item Builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\QuoteDetails\ItemBuilder
+     */
+    protected $_quoteDetailsItemBuilder;
+
+    /**
+     * Group Service Interface
+     *
+     * @var \Magento\Customer\Service\V1\CustomerGroupServiceInterface
+     */
+    protected $_groupService;
+
+    /**
+     * Default customer tax classId
+     *
+     * @var int
+     */
+    protected $_defaultCustomerTaxClassId;
+
+    /**
+     * Region  factory
+     *
+     * @var \Magento\Directory\Model\RegionFactory
+     */
+    protected $_regionFactory;
+
     /**
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Catalog\Model\ProductFactory $productFactory
-     * @param \Magento\GoogleShopping\Helper\Data $gsData
+     * @param \Magento\GoogleShopping\Helper\Data $googleShoppingHelper
      * @param \Magento\GoogleShopping\Helper\Product $gsProduct
      * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice
      * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource
      * @param \Magento\GoogleShopping\Model\Config $config
      * @param \Magento\Tax\Helper\Data $taxData
-     * @param \Magento\Tax\Model\Calculation $calculation
+     * @param \Magento\Tax\Service\V1\TaxRuleService $taxRuleService
+     * @param \Magento\Tax\Service\V1\TaxCalculationService $taxCalculationService
+     * @param \Magento\Tax\Service\V1\Data\QuoteDetailsBuilder $quoteDetailsBuilder
+     * @param \Magento\Tax\Service\V1\Data\QuoteDetails\ItemBuilder $quoteDetailsItemBuilder
+     * @param \Magento\Customer\Service\V1\CustomerGroupServiceInterface $groupServiceInterface
+     * @param \Magento\Directory\Model\RegionFactory $regionFactory
      * @param \Magento\Framework\Data\Collection\Db $resourceCollection
      * @param array $data
      */
@@ -70,24 +123,34 @@ class Tax extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
         \Magento\Framework\Model\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Catalog\Model\ProductFactory $productFactory,
-        \Magento\GoogleShopping\Helper\Data $gsData,
+        \Magento\GoogleShopping\Helper\Data $googleShoppingHelper,
         \Magento\GoogleShopping\Helper\Product $gsProduct,
         \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice,
         \Magento\GoogleShopping\Model\Resource\Attribute $resource,
         \Magento\GoogleShopping\Model\Config $config,
         \Magento\Tax\Helper\Data $taxData,
-        \Magento\Tax\Model\Calculation $calculation,
+        \Magento\Tax\Service\V1\TaxRuleService $taxRuleService,
+        \Magento\Tax\Service\V1\TaxCalculationService $taxCalculationService,
+        \Magento\Tax\Service\V1\Data\QuoteDetailsBuilder $quoteDetailsBuilder,
+        \Magento\Tax\Service\V1\Data\QuoteDetails\ItemBuilder $quoteDetailsItemBuilder,
+        \Magento\Customer\Service\V1\CustomerGroupServiceInterface $groupServiceInterface,
+        \Magento\Directory\Model\RegionFactory $regionFactory,
         \Magento\Framework\Data\Collection\Db $resourceCollection = null,
         array $data = array()
     ) {
         $this->_config = $config;
         $this->_taxData = $taxData;
-        $this->calculation = $calculation;
+        $this->_taxRuleService = $taxRuleService;
+        $this->_taxCalculationService = $taxCalculationService;
+        $this->_quoteDetailsBuilder = $quoteDetailsBuilder;
+        $this->_quoteDetailsItemBuilder = $quoteDetailsItemBuilder;
+        $this->_groupService = $groupServiceInterface;
+        $this->_regionFactory = $regionFactory;
         parent::__construct(
             $context,
             $registry,
             $productFactory,
-            $gsData,
+            $googleShoppingHelper,
             $gsProduct,
             $catalogPrice,
             $resource,
@@ -102,6 +165,7 @@ class Tax extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
      * @param \Magento\Catalog\Model\Product $product
      * @param \Magento\Framework\Gdata\Gshopping\Entry $entry
      * @return \Magento\Framework\Gdata\Gshopping\Entry
+     * @throws \Magento\Framework\Model\Exception
      */
     public function convertAttribute($product, $entry)
     {
@@ -110,14 +174,18 @@ class Tax extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
             return $entry;
         }
 
-        $calc = $this->calculation;
-        $customerTaxClass = $calc->getDefaultCustomerTaxClass($product->getStoreId());
-        $rates = $calc->getRatesByCustomerAndProductTaxClasses($customerTaxClass, $product->getTaxClassId());
+        $defaultCustomerTaxClassId = $this->_getDefaultCustomerTaxClassId($product->getStoreId());
+        $rates = $this->_taxRuleService->getRatesByCustomerAndProductTaxClassId(
+            $defaultCustomerTaxClassId,
+            $product->getTaxClassId()
+        );
         $targetCountry = $this->_config->getTargetCountry($product->getStoreId());
         $ratesTotal = 0;
         foreach ($rates as $rate) {
-            if ($targetCountry == $rate['country']) {
-                $regions = $this->_parseRegions($rate['state'], $rate['postcode']);
+            $countryId = $rate->getCountryId();
+            $postcode = $rate->getPostcode();
+            if ($targetCountry == $countryId) {
+                $regions = $this->_getRegionsByRegionId($rate->getRegionId(), $postcode);
                 $ratesTotal += count($regions);
                 if ($ratesTotal > self::RATES_MAX) {
                     throw new \Magento\Framework\Model\Exception(
@@ -125,12 +193,65 @@ class Tax extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
                     );
                 }
                 foreach ($regions as $region) {
+                    $adjustments = $product->getPriceInfo()->getAdjustments();
+                    if (array_key_exists('tax', $adjustments)) {
+                        $taxIncluded = true;
+                    } else {
+                        $taxIncluded = false;
+                    }
+
+                    $quoteDetailsItemDataArray = [
+                        'code' => $product->getSku(),
+                        'type' => 'product',
+                        'tax_class_key' => [
+                            TaxClassKey::KEY_TYPE => TaxClassKey::TYPE_ID,
+                            TaxClassKey::KEY_VALUE => $product->getTaxClassId(),
+                        ],
+                        'unit_price' => $product->getPrice(),
+                        'quantity' => 1,
+                        'tax_included' => $taxIncluded,
+                        'short_description' => $product->getName(),
+                    ];
+
+                    $billingAddressDataArray = [
+                        'country_id' => $countryId,
+                        'region' => ['region_id' => $rate->getRegionId()],
+                        'postcode' => $postcode,
+                    ];
+
+                    $shippingAddressDataArray = [
+                        'country_id' => $countryId,
+                        'region' => ['region_id' => $rate->getRegionId()],
+                        'postcode' => $postcode,
+                    ];
+
+                    $quoteDetailsDataArray = [
+                        'billing_address' => $billingAddressDataArray,
+                        'shipping_address' => $shippingAddressDataArray,
+                        'customer_tax_class_key' => [
+                            TaxClassKey::KEY_TYPE => TaxClassKey::TYPE_ID,
+                            TaxClassKey::KEY_VALUE => $defaultCustomerTaxClassId,
+                        ],
+                        'items' => [
+                            $quoteDetailsItemDataArray,
+                        ],
+                    ];
+
+                    $quoteDetailsObject = $this->_quoteDetailsBuilder
+                        ->populateWithArray($quoteDetailsDataArray)
+                        ->create();
+
+                    $taxDetails = $this->_taxCalculationService
+                        ->calculateTax($quoteDetailsObject, $product->getStoreId());
+
+                    $taxRate = ($taxDetails->getTaxAmount() / $taxDetails->getSubtotal()) * 100;
+
                     $entry->addTax(
-                        array(
-                            'tax_rate' => $rate['value'] * 100,
-                            'tax_country' => empty($rate['country']) ? '*' : $rate['country'],
-                            'tax_region' => $region
-                        )
+                        [
+                            'tax_rate' => $taxRate,
+                            'tax_country' => $countryId,
+                            'tax_region' => $region,
+                        ]
                     );
                 }
             }
@@ -140,137 +261,35 @@ class Tax extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
     }
 
     /**
-     * Retrieve array of regions characterized by provided params
-     *
-     * @param string $state
-     * @param string $zip
-     * @return string[]
-     */
-    protected function _parseRegions($state, $zip)
-    {
-        return !empty($zip) && $zip != '*' ? $this->_parseZip($zip) : ($state ? array($state) : array('*'));
-    }
-
-    /**
-     * Retrieve array of regions characterized by provided zip code
+     * Fetch default customer tax classId
      *
-     * @param string $zip
-     * @return string[]
+     * @param null|Store|string|int $store
+     * @return int
      */
-    protected function _parseZip($zip)
+    private function _getDefaultCustomerTaxClassId($store = null)
     {
-        if (strpos($zip, '-') == -1) {
-            return array($zip);
-        } else {
-            return $this->zipRangeToZipPattern($zip);
+        if (is_null($this->_defaultCustomerTaxClassId)) {
+            //Not catching the exception here since default group is expected
+            $defaultCustomerGroup = $this->_groupService->getDefaultGroup($store);
+            $this->_defaultCustomerTaxClassId = $defaultCustomerGroup->getTaxClassId();
         }
+        return $this->_defaultCustomerTaxClassId;
     }
 
     /**
-     * Convert Magento zip range to array of Google Shopping zip-patterns
-     * (e.g., 12000-13999 -> [12*, 13*])
+     * Get regions by region ID
      *
-     * @param  string $zipRange
-     * @return array
+     * @param int $regionId
+     * @param string $postalCode
+     * @return String[]
      */
-    private function zipRangeToZipPattern($zipRange)
+    private function _getRegionsByRegionId($regionId, $postalCode)
     {
-        $zipLength = 5;
-        $zipPattern = array();
-
-        if (!preg_match("/^(.+)-(.+)$/", $zipRange, $zipParts)) {
-            return array($zipRange);
+        $regions = [];
+        $regionCode = $this->_regionFactory->create()->load($regionId)->getCode();
+        if (!is_null($regionCode)) {
+            $regions = Zip::parseRegions($regionCode, $postalCode);
         }
-
-        if ($zipParts[1] == $zipParts[2]) {
-            return array($zipParts[1]);
-        }
-
-        if ($zipParts[1] > $zipParts[2]) {
-            list($zipParts[2], $zipParts[1]) = array($zipParts[1], $zipParts[2]);
-        }
-
-        $from = str_split($zipParts[1]);
-        $to = str_split($zipParts[2]);
-
-        $startZip = '';
-        $diffPosition = null;
-        for ($pos = 0; $pos < $zipLength; $pos++) {
-            if ($from[$pos] == $to[$pos]) {
-                $startZip .= $from[$pos];
-            } else {
-                $diffPosition = $pos;
-                break;
-            }
-        }
-
-        /*
-         * calculate zip-patterns
-         */
-        if (min(array_slice($to, $diffPosition)) == 9 && max(array_slice($from, $diffPosition)) == 0) {
-            // particular case like 11000-11999 -> 11*
-            return array($startZip . '*');
-        } else {
-            // calculate approximate zip-patterns
-            $start = $from[$diffPosition];
-            $finish = $to[$diffPosition];
-            if ($diffPosition < $zipLength - 1) {
-                $start++;
-                $finish--;
-            }
-            $end = $diffPosition < $zipLength - 1 ? '*' : '';
-            for ($digit = $start; $digit <= $finish; $digit++) {
-                $zipPattern[] = $startZip . $digit . $end;
-            }
-        }
-
-        if ($diffPosition == $zipLength - 1) {
-            return $zipPattern;
-        }
-
-        $nextAsteriskFrom = true;
-        $nextAsteriskTo = true;
-        for ($pos = $zipLength - 1; $pos > $diffPosition; $pos--) {
-            // calculate zip-patterns based on $from value
-            if ($from[$pos] == 0 && $nextAsteriskFrom) {
-                $nextAsteriskFrom = true;
-            } else {
-                $subZip = '';
-                for ($k = $diffPosition; $k < $pos; $k++) {
-                    $subZip .= $from[$k];
-                }
-                $delta = $nextAsteriskFrom ? 0 : 1;
-                $end = $pos < $zipLength - 1 ? '*' : '';
-                for ($i = $from[$pos] + $delta; $i <= 9; $i++) {
-                    $zipPattern[] = $startZip . $subZip . $i . $end;
-                }
-                $nextAsteriskFrom = false;
-            }
-
-            // calculate zip-patterns based on $to value
-            if ($to[$pos] == 9 && $nextAsteriskTo) {
-                $nextAsteriskTo = true;
-            } else {
-                $subZip = '';
-                for ($k = $diffPosition; $k < $pos; $k++) {
-                    $subZip .= $to[$k];
-                }
-                $delta = $nextAsteriskTo ? 0 : 1;
-                $end = $pos < $zipLength - 1 ? '*' : '';
-                for ($i = 0; $i <= $to[$pos] - $delta; $i++) {
-                    $zipPattern[] = $startZip . $subZip . $i . $end;
-                }
-                $nextAsteriskTo = false;
-            }
-        }
-
-        if ($nextAsteriskFrom) {
-            $zipPattern[] = $startZip . $from[$diffPosition] . '*';
-        }
-        if ($nextAsteriskTo) {
-            $zipPattern[] = $startZip . $to[$diffPosition] . '*';
-        }
-
-        return $zipPattern;
+        return $regions;
     }
 }
diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/Title.php b/app/code/Magento/GoogleShopping/Model/Attribute/Title.php
index f43f1c8f6b96a57983a125001f65a7c44e1728e5..8c6174fe97c103c4714e8abf657da2cf3783ea82 100644
--- a/app/code/Magento/GoogleShopping/Model/Attribute/Title.php
+++ b/app/code/Magento/GoogleShopping/Model/Attribute/Title.php
@@ -53,7 +53,7 @@ class Title extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute
         } else {
             $titleText = 'no title';
         }
-        $titleText = $this->_gsData->cleanAtomAttribute($titleText);
+        $titleText = $this->_googleShoppingHelper->cleanAtomAttribute($titleText);
         $entry->setTitle($entry->getService()->newTitle()->setText($titleText));
 
         return $entry;
diff --git a/app/code/Magento/GoogleShopping/Model/AttributeFactory.php b/app/code/Magento/GoogleShopping/Model/AttributeFactory.php
index 348007fc95184517b3869cacc3d393be4e5be8c2..6bf5a8df2e7187a2b74a093fce6d77d3c63586a7 100644
--- a/app/code/Magento/GoogleShopping/Model/AttributeFactory.php
+++ b/app/code/Magento/GoogleShopping/Model/AttributeFactory.php
@@ -42,7 +42,7 @@ class AttributeFactory
      *
      * @var \Magento\GoogleShopping\Helper\Data
      */
-    protected $_gsData;
+    protected $_googleShoppingHelper;
 
     /**
      * @var \Magento\Framework\Stdlib\String
@@ -51,16 +51,16 @@ class AttributeFactory
 
     /**
      * @param \Magento\Framework\ObjectManager $objectManager
-     * @param \Magento\GoogleShopping\Helper\Data $gsData
+     * @param \Magento\GoogleShopping\Helper\Data $googleShoppingHelper
      * @param \Magento\Framework\Stdlib\String $string
      */
     public function __construct(
         \Magento\Framework\ObjectManager $objectManager,
-        \Magento\GoogleShopping\Helper\Data $gsData,
+        \Magento\GoogleShopping\Helper\Data $googleShoppingHelper,
         \Magento\Framework\Stdlib\String $string
     ) {
         $this->_objectManager = $objectManager;
-        $this->_gsData = $gsData;
+        $this->_googleShoppingHelper = $googleShoppingHelper;
         $this->_string = $string;
     }
 
@@ -73,7 +73,7 @@ class AttributeFactory
     public function createAttribute($name)
     {
         $modelName = 'Magento\GoogleShopping\Model\Attribute\\' . $this->_string->upperCaseWords(
-            $this->_gsData->normalizeName($name)
+            $this->_googleShoppingHelper->normalizeName($name)
         );
         try {
             /** @var \Magento\GoogleShopping\Model\Attribute\DefaultAttribute $attributeModel */
diff --git a/app/code/Magento/GoogleShopping/Model/Service/Item.php b/app/code/Magento/GoogleShopping/Model/Service/Item.php
index c019a452f088dc9d901628d52fd04684fff3d5c7..4290b98084ab456b6bee55fbf121ac86d7c2447f 100644
--- a/app/code/Magento/GoogleShopping/Model/Service/Item.php
+++ b/app/code/Magento/GoogleShopping/Model/Service/Item.php
@@ -33,7 +33,7 @@ class Item extends \Magento\GoogleShopping\Model\Service
     /**
      * @var \Magento\GoogleShopping\Helper\Data|null
      */
-    protected $_gsData = null;
+    protected $_googleShoppingHelper = null;
 
     /**
      * Date
@@ -48,7 +48,7 @@ class Item extends \Magento\GoogleShopping\Model\Service
      * @param \Magento\GoogleShopping\Model\Config $config
      * @param \Magento\Framework\Gdata\Gshopping\ContentFactory $contentFactory
      * @param \Magento\Framework\Stdlib\DateTime\DateTime $date
-     * @param \Magento\GoogleShopping\Helper\Data $gsData
+     * @param \Magento\GoogleShopping\Helper\Data $googleShoppingHelper
      * @param array $data
      */
     public function __construct(
@@ -57,11 +57,11 @@ class Item extends \Magento\GoogleShopping\Model\Service
         \Magento\GoogleShopping\Model\Config $config,
         \Magento\Framework\Gdata\Gshopping\ContentFactory $contentFactory,
         \Magento\Framework\Stdlib\DateTime\DateTime $date,
-        \Magento\GoogleShopping\Helper\Data $gsData,
+        \Magento\GoogleShopping\Helper\Data $googleShoppingHelper,
         array $data = array()
     ) {
         $this->_date = $date;
-        $this->_gsData = $gsData;
+        $this->_googleShoppingHelper = $googleShoppingHelper;
         parent::__construct($logAdapterFactory, $coreRegistry, $config, $contentFactory, $data);
     }
 
@@ -179,7 +179,7 @@ class Item extends \Magento\GoogleShopping\Model\Service
         $service = $this->getService($storeId);
 
         $countryInfo = $this->getConfig()->getTargetCountryInfo($storeId);
-        $itemId = $this->_gsData->buildContentProductId($item->getProductId(), $item->getStoreId());
+        $itemId = $this->_googleShoppingHelper->buildContentProductId($item->getProductId(), $item->getStoreId());
 
         $query = $service->newItemQuery()->setId(
             $itemId
diff --git a/app/code/Magento/GoogleShopping/Model/Type.php b/app/code/Magento/GoogleShopping/Model/Type.php
index a28b53898a8ad7ff1103bd94688f3f2cf71dc635..0b6abaaa80aa9986d64e388e0f382799e0e0a213 100644
--- a/app/code/Magento/GoogleShopping/Model/Type.php
+++ b/app/code/Magento/GoogleShopping/Model/Type.php
@@ -48,7 +48,7 @@ class Type extends \Magento\Framework\Model\AbstractModel
     /**
      * @var \Magento\GoogleShopping\Helper\Data
      */
-    protected $_gsData;
+    protected $_googleShoppingHelper;
 
     /**
      * Config
@@ -78,7 +78,7 @@ class Type extends \Magento\Framework\Model\AbstractModel
      * @param \Magento\GoogleShopping\Model\AttributeFactory $attributeFactory
      * @param \Magento\GoogleShopping\Model\Config $config
      * @param \Magento\GoogleShopping\Helper\Product $gsProduct
-     * @param \Magento\GoogleShopping\Helper\Data $gsData
+     * @param \Magento\GoogleShopping\Helper\Data $googleShoppingHelper
      * @param \Magento\GoogleShopping\Model\Resource\Type $resource
      * @param \Magento\Framework\Data\Collection\Db $resourceCollection
      * @param array $data
@@ -90,7 +90,7 @@ class Type extends \Magento\Framework\Model\AbstractModel
         \Magento\GoogleShopping\Model\AttributeFactory $attributeFactory,
         \Magento\GoogleShopping\Model\Config $config,
         \Magento\GoogleShopping\Helper\Product $gsProduct,
-        \Magento\GoogleShopping\Helper\Data $gsData,
+        \Magento\GoogleShopping\Helper\Data $googleShoppingHelper,
         \Magento\GoogleShopping\Model\Resource\Type $resource,
         \Magento\Framework\Data\Collection\Db $resourceCollection = null,
         array $data = array()
@@ -99,7 +99,7 @@ class Type extends \Magento\Framework\Model\AbstractModel
         $this->_attributeFactory = $attributeFactory;
         $this->_config = $config;
         $this->_gsProduct = $gsProduct;
-        $this->_gsData = $gsData;
+        $this->_googleShoppingHelper = $googleShoppingHelper;
         parent::__construct($context, $registry, $resource, $resourceCollection, $data);
     }
 
@@ -167,7 +167,7 @@ class Type extends \Magento\Framework\Model\AbstractModel
                 }
 
                 if (!is_null($name)) {
-                    $name = $this->_gsData->normalizeName($name);
+                    $name = $this->_googleShoppingHelper->normalizeName($name);
                     if (isset($group[$name])) {
                         // if attribute is in the group
                         if (!isset($result[$group[$name]])) {
@@ -271,7 +271,7 @@ class Type extends \Magento\Framework\Model\AbstractModel
 
         $contentAttributes = $entry->getContentAttributes();
         foreach ($contentAttributes as $contentAttribute) {
-            $name = $this->_gsData->normalizeName($contentAttribute->getName());
+            $name = $this->_googleShoppingHelper->normalizeName($contentAttribute->getName());
             if (!in_array($name, $ignoredAttributes) && !in_array($existAttributes, $existAttributes)) {
                 $entry->removeContentAttribute($name);
             }
diff --git a/app/code/Magento/GoogleShopping/etc/module.xml b/app/code/Magento/GoogleShopping/etc/module.xml
index f9ef0d68485ea0cb2c2dbef90f8fcc78eee13c16..e7a52ba4ee9d9cb341176533db76eaff10f58ae9 100644
--- a/app/code/Magento/GoogleShopping/etc/module.xml
+++ b/app/code/Magento/GoogleShopping/etc/module.xml
@@ -35,6 +35,7 @@
             <module name="Magento_Backend"/>
             <module name="Magento_Catalog"/>
             <module name="Magento_Customer"/>
+            <module name="Magento_Directory"/>
             <module name="Magento_Eav"/>
             <module name="Magento_Tax"/>
             <module name="Magento_Theme"/>
diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/templates/product/grouped/grouped.phtml b/app/code/Magento/GroupedProduct/view/adminhtml/templates/product/grouped/grouped.phtml
index 938cfd1d7b822fde5cbf5157c7ca3e82a0b3ca05..e5b190893d849e3b47e5a25fbff46593a8dc8b45 100644
--- a/app/code/Magento/GroupedProduct/view/adminhtml/templates/product/grouped/grouped.phtml
+++ b/app/code/Magento/GroupedProduct/view/adminhtml/templates/product/grouped/grouped.phtml
@@ -30,7 +30,7 @@ $_gridPopupBlock->setRowClickCallback('function(){}');
 /** @var $_helper \Magento\Core\Helper\Data */
 $_helper = $this->helper('Magento\Core\Helper\Data');
 ?>
-<div id="grouped-product-container" data-mage-init='{"groupedProduct":{"gridPopup":"window.<?php echo $_gridPopupBlock->getJsObjectName() ?>"}}'>
+<div id="grouped-product-container" data-mage-init='{"groupedProduct":{"gridPopup":"[data-grid-id=<?php echo $_gridPopupBlock->getId() ?>]"}}'>
     <div class="no-products-message">
         <?php echo __('There are no grouped products.')?>
     </div>
diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/web/js/grouped-product.js b/app/code/Magento/GroupedProduct/view/adminhtml/web/js/grouped-product.js
index 7658e52cc489496b40986ac19de3f35f2eb18c48..fb5593438531047e5947e4c4e939373cc1169351 100644
--- a/app/code/Magento/GroupedProduct/view/adminhtml/web/js/grouped-product.js
+++ b/app/code/Magento/GroupedProduct/view/adminhtml/web/js/grouped-product.js
@@ -159,7 +159,7 @@
                 }, this)
             );
 
-            var gridPopup = this.options.gridPopup;
+            var gridPopup = $(this.options.gridPopup).data('gridObject');
 
             $('[data-role=add-product]').on('click', function(event) {
                 event.preventDefault();
diff --git a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml
index b942832e44e419dcd0734cfc4399446e9509ebc1..c1ded611880a2d907fc39c3469d4f8a2c3860ac2 100644
--- a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml
+++ b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml
@@ -34,7 +34,7 @@
 <?php $_associatedProducts = $this->getAssociatedProducts(); ?>
 <?php $_hasAssociatedProducts = count($_associatedProducts) > 0; ?>
 
-<div class="wrapper table grouped">
+<div class="table-wrapper grouped">
     <table class="table data grouped" id="super-product-table">
         <caption class="table caption"><?php echo __('Grouped product items') ?></caption>
         <thead>
diff --git a/app/code/Magento/Multishipping/Controller/Checkout/OverviewPost.php b/app/code/Magento/Multishipping/Controller/Checkout/OverviewPost.php
index 0f803c9a62abf8c15c49c9a8a72f1319adc7f02f..7d47d2acc8a837d655e38c05056cd0f04ea11b5d 100644
--- a/app/code/Magento/Multishipping/Controller/Checkout/OverviewPost.php
+++ b/app/code/Magento/Multishipping/Controller/Checkout/OverviewPost.php
@@ -24,10 +24,36 @@
  */
 namespace Magento\Multishipping\Controller\Checkout;
 
+use Magento\Checkout\Controller\Action;
+use Magento\Customer\Service\V1\CustomerAccountServiceInterface as CustomerAccountService;
+use Magento\Customer\Service\V1\CustomerMetadataServiceInterface as CustomerMetadataService;
 use \Magento\Multishipping\Model\Checkout\Type\Multishipping\State;
 
 class OverviewPost extends \Magento\Multishipping\Controller\Checkout
 {
+    /**
+     * @var \Magento\Core\App\Action\FormKeyValidator
+     */
+    protected $formKeyValidator;
+
+    /**
+     * @param \Magento\Framework\App\Action\Context $context
+     * @param \Magento\Customer\Model\Session $customerSession
+     * @param CustomerAccountService $customerAccountService
+     * @param CustomerMetadataService $customerMetadataService
+     * @param \Magento\Core\App\Action\FormKeyValidator $formKeyValidator
+     */
+    public function __construct(
+        \Magento\Framework\App\Action\Context $context,
+        \Magento\Customer\Model\Session $customerSession,
+        CustomerAccountService $customerAccountService,
+        CustomerMetadataService $customerMetadataService,
+        \Magento\Core\App\Action\FormKeyValidator $formKeyValidator
+    ) {
+        $this->formKeyValidator = $formKeyValidator;
+        parent::__construct($context, $customerSession, $customerAccountService, $customerMetadataService);
+    }
+
     /**
      * Overview action
      *
@@ -35,6 +61,10 @@ class OverviewPost extends \Magento\Multishipping\Controller\Checkout
      */
     public function execute()
     {
+        if (!$this->formKeyValidator->validate($this->getRequest())) {
+            $this->_forward('backToAddresses');
+            return;
+        }
         if (!$this->_validateMinimumAmount()) {
             return;
         }
diff --git a/app/code/Magento/Multishipping/etc/module.xml b/app/code/Magento/Multishipping/etc/module.xml
index 31cfef37fe5e6023aa3c5291575fda9b2e94ba89..2002818416e401d4e75a15ceeda36654b532f3fc 100644
--- a/app/code/Magento/Multishipping/etc/module.xml
+++ b/app/code/Magento/Multishipping/etc/module.xml
@@ -39,6 +39,7 @@
             <module name="Magento_Tax"/>
             <module name="Magento_Customer"/>
             <module name="Magento_Weee"/>
+            <module name="Magento_Theme"/>
         </depends>
     </module>
 </config>
diff --git a/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml b/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml
index 67392762626595ce725ef117e7c40f495d3ce5a5..e619ce52635ae346c4797732d200ba74aa1fddf2 100644
--- a/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml
+++ b/app/code/Magento/Multishipping/view/frontend/templates/checkout/addresses.phtml
@@ -36,7 +36,7 @@
     </div>
     <input type="hidden" name="continue" value="0" id="can_continue_flag"/>
     <input type="hidden" name="new_address" value="0" id="add_new_address_flag"/>
-    <div class="wrapper table">
+    <div class="table-wrapper">
         <table class="items data table" id="multiship-addresses-table">
             <caption class="table caption"><?php echo __('Please select a shipping address for applicable items.') ?></caption>
             <thead>
diff --git a/app/code/Magento/Multishipping/view/frontend/templates/checkout/overview.phtml b/app/code/Magento/Multishipping/view/frontend/templates/checkout/overview.phtml
index 0db201927252e86040a62e524fd91a5c9f5138a2..5a792124164d37b6feaad545c7397fef5287dcf9 100644
--- a/app/code/Magento/Multishipping/view/frontend/templates/checkout/overview.phtml
+++ b/app/code/Magento/Multishipping/view/frontend/templates/checkout/overview.phtml
@@ -22,8 +22,8 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 ?>
-<?php /** @var $this \Magento\Multishipping\Block\Checkout\Overview */ ?>
 <form action="<?php echo $this->getPostActionUrl() ?>" method="post" id="review-order-form" data-mage-init='{"orderOverview": {}}' class="form multicheckout overview">
+    <?php echo $this->getBlockHtml('formkey'); ?>
     <div class="block billing">
         <div class="title"><strong><?php echo __('Billing Information') ?></strong></div>
         <div class="content">
diff --git a/app/code/Magento/Multishipping/view/frontend/templates/checkout/shipping.phtml b/app/code/Magento/Multishipping/view/frontend/templates/checkout/shipping.phtml
index 6cf29ce77f7b17fcf0cd1da646c9a480d8f145af..bbd4fa7ef9c46531cfae1682d937a9733874a349 100644
--- a/app/code/Magento/Multishipping/view/frontend/templates/checkout/shipping.phtml
+++ b/app/code/Magento/Multishipping/view/frontend/templates/checkout/shipping.phtml
@@ -86,7 +86,7 @@
                     <span><?php echo __('Items') ?></span>
                     <a href="<?php echo $this->getItemsEditUrl($_address) ?>" class="action edit"><span><?php echo __('Edit Items') ?></span></a>
                 </strong>
-                <div class="wrapper table">
+                <div class="table-wrapper">
                     <table class="items data table" id="shipping-table-<?php echo $_address->getId() ?>">
                         <caption class="table caption"><?php echo __('Items') ?></caption>
                         <thead>
diff --git a/app/code/Magento/OfflinePayments/view/frontend/templates/info/checkmo.phtml b/app/code/Magento/OfflinePayments/view/frontend/templates/info/checkmo.phtml
index 0905d2eec6135c39fbba2e90c64a61e274957de9..3aadaa9ce066ad8d0b356f61a591d0e5b2c8dcbd 100644
--- a/app/code/Magento/OfflinePayments/view/frontend/templates/info/checkmo.phtml
+++ b/app/code/Magento/OfflinePayments/view/frontend/templates/info/checkmo.phtml
@@ -22,7 +22,7 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 ?>
-<dl class="payment method checkmemo">
+<dl class="payment-method checkmemo">
     <dt class="title"><?php echo $this->escapeHtml($this->getMethod()->getTitle()) ?></dt>
     <?php if($this->getInfo()->getAdditionalData()): ?>
         <?php if($this->getPayableTo()): ?>
diff --git a/app/code/Magento/OfflinePayments/view/frontend/templates/info/purchaseorder.phtml b/app/code/Magento/OfflinePayments/view/frontend/templates/info/purchaseorder.phtml
index 209cf87e7f1c9ae9cd8e596a045a9fddd2af72ac..878a144e74507a75c2498f0207e27a0558e92029 100644
--- a/app/code/Magento/OfflinePayments/view/frontend/templates/info/purchaseorder.phtml
+++ b/app/code/Magento/OfflinePayments/view/frontend/templates/info/purchaseorder.phtml
@@ -22,7 +22,7 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 ?>
-<dl class="payment method purchase order">
+<dl class="payment-method purchase order">
     <dt class="title"><?php echo $this->escapeHtml($this->getMethod()->getTitle()) ?></dt>
     <dd class="content">
         <strong><?php echo __('Purchase Order Number') ?></strong>
diff --git a/app/code/Magento/OfflineShipping/Controller/Adminhtml/System/Config/ExportTablerates.php b/app/code/Magento/OfflineShipping/Controller/Adminhtml/System/Config/ExportTablerates.php
index 4ff66cddf0d42c36c44d17c11f298be585e4fba4..19468bff577504b0f5c94c5f4f7193a7aa2cea08 100644
--- a/app/code/Magento/OfflineShipping/Controller/Adminhtml/System/Config/ExportTablerates.php
+++ b/app/code/Magento/OfflineShipping/Controller/Adminhtml/System/Config/ExportTablerates.php
@@ -25,6 +25,7 @@
 namespace Magento\OfflineShipping\Controller\Adminhtml\System\Config;
 
 use \Magento\Framework\App\ResponseInterface;
+use Magento\Backend\Controller\Adminhtml\System\ConfigSectionChecker;
 
 class ExportTablerates extends \Magento\Backend\Controller\Adminhtml\System\AbstractConfig
 {
@@ -41,18 +42,20 @@ class ExportTablerates extends \Magento\Backend\Controller\Adminhtml\System\Abst
     /**
      * @param \Magento\Backend\App\Action\Context $context
      * @param \Magento\Backend\Model\Config\Structure $configStructure
+     * @param ConfigSectionChecker $sectionChecker
      * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
      */
     public function __construct(
         \Magento\Backend\App\Action\Context $context,
         \Magento\Backend\Model\Config\Structure $configStructure,
+        ConfigSectionChecker $sectionChecker,
         \Magento\Framework\App\Response\Http\FileFactory $fileFactory,
         \Magento\Store\Model\StoreManagerInterface $storeManager
     ) {
         $this->_storeManager = $storeManager;
         $this->_fileFactory = $fileFactory;
-        parent::__construct($context, $configStructure);
+        parent::__construct($context, $configStructure, $sectionChecker);
     }
 
     /**
diff --git a/app/code/Magento/OfflineShipping/Model/SalesRule/Calculator.php b/app/code/Magento/OfflineShipping/Model/SalesRule/Calculator.php
index 01f06ce909d35df2b119a9fbebe82b418f802e13..d663064337b7f21e125b9664bfbb01d460d42d77 100644
--- a/app/code/Magento/OfflineShipping/Model/SalesRule/Calculator.php
+++ b/app/code/Magento/OfflineShipping/Model/SalesRule/Calculator.php
@@ -47,7 +47,7 @@ class Calculator extends \Magento\SalesRule\Model\Validator
 
         foreach ($this->_getRules() as $rule) {
             /* @var $rule \Magento\SalesRule\Model\Rule */
-            if (!$this->_canProcessRule($rule, $address)) {
+            if (!$this->validatorUtility->canProcessRule($rule, $address)) {
                 continue;
             }
 
diff --git a/app/code/Magento/Ogone/Controller/Api.php b/app/code/Magento/Ogone/Controller/Api.php
index 61ab2da4e166aa7ba73ddd4d06be4ff1f24db2c1..0a3493b972842eeba1e5daffbeb13cf4223b30aa 100644
--- a/app/code/Magento/Ogone/Controller/Api.php
+++ b/app/code/Magento/Ogone/Controller/Api.php
@@ -24,6 +24,7 @@
 namespace Magento\Ogone\Controller;
 
 use Magento\Sales\Model\Order;
+use Magento\Sales\Model\Order\Payment\Transaction as PaymentTransaction;
 
 /**
  * Ogone Api Controller
@@ -238,6 +239,8 @@ class Api extends \Magento\Framework\App\Action\Action
                     );
                 }
 
+                $order->getPayment()->addTransaction(PaymentTransaction::TYPE_CAPTURE);
+
                 if (!$order->getInvoiceCollection()->getSize()) {
                     $invoice = $order->prepareInvoice();
                     $invoice->register();
@@ -286,6 +289,8 @@ class Api extends \Magento\Framework\App\Action\Action
                     \Magento\Ogone\Model\Api::PROCESSED_OGONE_STATUS,
                     __('Processed by Ogone')
                 );
+
+                $order->getPayment()->addTransaction(PaymentTransaction::TYPE_AUTH);
             }
             $order->save();
             $this->_redirect('checkout/onepage/success');
diff --git a/app/code/Magento/Payment/Helper/Data.php b/app/code/Magento/Payment/Helper/Data.php
index 31922a11e37ca55545aa17895f3dd802decdf9ab..8e88cbe898ee6d3985b2ec338ab35f16fb91620e 100644
--- a/app/code/Magento/Payment/Helper/Data.php
+++ b/app/code/Magento/Payment/Helper/Data.php
@@ -131,7 +131,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
     {
         $res = array();
         $methods = $this->getPaymentMethods();
-        uasort($methods, array($this, '_sortMethods'));
+
         foreach ($methods as $code => $methodConfig) {
             $prefix = self::XML_PATH_PAYMENT_METHODS . '/' . $code . '/';
             if (!($model = $this->_scopeConfig->getValue(
@@ -142,10 +142,12 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
             ) {
                 continue;
             }
+
             $methodInstance = $this->_methodFactory->create($model);
             if (!$methodInstance) {
                 continue;
             }
+
             $methodInstance->setStore($store);
             if (!$methodInstance->isAvailable($quote)) {
                 /* if the payment method cannot be used at this time */
@@ -156,22 +158,23 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
             $res[] = $methodInstance;
         }
 
+        uasort($res, array($this, '_sortMethods'));
+
         return $res;
     }
 
     /**
-     * @param $mixed $a
-     * @param $mixed $b
+     * Sort payments methods
+     *
+     * @param \Magento\Payment\Model\MethodInterface $a
+     * @param \Magento\Payment\Model\MethodInterface $b
      * @return int
      */
     protected function _sortMethods($a, $b)
     {
-        if (is_object($a)) {
-            return (int)$a->sort_order <
-                (int)$b->sort_order ? -1 : ((int)$a->sort_order >
-                (int)$b->sort_order ? 1 : 0);
-        }
-        return 0;
+        return (int)$a->getSortOrder() <
+            (int)$b->getSortOrder() ? -1 : ((int)$a->getSortOrder() >
+            (int)$b->getSortOrder() ? 1 : 0);
     }
 
     /**
diff --git a/app/code/Magento/Payment/Model/Cart.php b/app/code/Magento/Payment/Model/Cart.php
index ef76137967c28130099864080e013efffd89dba9..6c2331673225755eb19563f0d5b27789ef721b1d 100644
--- a/app/code/Magento/Payment/Model/Cart.php
+++ b/app/code/Magento/Payment/Model/Cart.php
@@ -330,7 +330,8 @@ class Cart
             $this->_salesModelItems[] = $this->_createItemFromData(
                 $item->getName(),
                 $item->getQty(),
-                $item->getPrice()
+                $item->getPrice(),
+                $item->getOriginalItem()->getId()
             );
         }
 
diff --git a/app/code/Magento/Payment/view/frontend/templates/info/default.phtml b/app/code/Magento/Payment/view/frontend/templates/info/default.phtml
index c97dd7122211a985eb0d96a75b19face49fc6509..ac25bb48acd938630352bd5d510cecbb2dea3f88 100644
--- a/app/code/Magento/Payment/view/frontend/templates/info/default.phtml
+++ b/app/code/Magento/Payment/view/frontend/templates/info/default.phtml
@@ -27,7 +27,7 @@
  * @see \Magento\Payment\Block\Info
  */
 ?>
-<dl class="payment method">
+<dl class="payment-method">
     <dt class="title"><?php echo $this->escapeHtml($this->getMethod()->getTitle()) ?></dt>
 <?php if ($_specificInfo = $this->getSpecificInformation()):?>
     <dd class="content">
diff --git a/app/code/Magento/Payment/view/frontend/templates/info/instructions.phtml b/app/code/Magento/Payment/view/frontend/templates/info/instructions.phtml
index 63e96500252fb6995b3a2d3f3d35f2f8d065a7ba..b2c83dfce58bc2cb8a03727ac8d4dea2e89f8603 100644
--- a/app/code/Magento/Payment/view/frontend/templates/info/instructions.phtml
+++ b/app/code/Magento/Payment/view/frontend/templates/info/instructions.phtml
@@ -27,7 +27,7 @@
  * @see \Magento\Payment\Block\Info
  */
 ?>
-<dl class="payment method">
+<dl class="payment-method">
     <dt class="title"><?php echo $this->escapeHtml($this->getMethod()->getTitle()) ?></dt>
 <?php if ($this->getInstructions()): ?>
     <dd class="content"><?php echo nl2br($this->getInstructions()) ?></dd>
diff --git a/app/code/Magento/Paypal/Block/Adminhtml/Billing/Agreement/Grid.php b/app/code/Magento/Paypal/Block/Adminhtml/Billing/Agreement/Grid.php
index 3daa62dc4a5f1aab7e3cb36745980c30b87e799b..05e2a4b7f49718d4e3cd7b94920307d196c94c82 100644
--- a/app/code/Magento/Paypal/Block/Adminhtml/Billing/Agreement/Grid.php
+++ b/app/code/Magento/Paypal/Block/Adminhtml/Billing/Agreement/Grid.php
@@ -194,7 +194,7 @@ class Grid extends \Magento\Backend\Block\Widget\Grid\Extended
             'created_at',
             array(
                 'header' => __('Created'),
-                'index' => 'agreement_created_at',
+                'index' => 'created_at',
                 'type' => 'datetime',
                 'align' => 'center',
                 'default' => __('N/A'),
@@ -208,7 +208,7 @@ class Grid extends \Magento\Backend\Block\Widget\Grid\Extended
             'updated_at',
             array(
                 'header' => __('Updated'),
-                'index' => 'agreement_updated_at',
+                'index' => 'updated_at',
                 'type' => 'datetime',
                 'align' => 'center',
                 'default' => __('N/A'),
diff --git a/app/code/Magento/Paypal/Block/Iframe.php b/app/code/Magento/Paypal/Block/Iframe.php
index 8960bf31dffa3b8ad78b1779bb6420f08b050c82..7d6559dbf5a78e0f91f6cf766188298fd05a1a7d 100644
--- a/app/code/Magento/Paypal/Block/Iframe.php
+++ b/app/code/Magento/Paypal/Block/Iframe.php
@@ -114,7 +114,7 @@ class Iframe extends \Magento\Payment\Block\Form
 
             $directory = $this->_filesystem->getDirectoryRead(\Magento\Framework\App\Filesystem::MODULES_DIR);
             $file = $this->_viewFileSystem->getTemplateFileName($templateFile, array('module' => 'Magento_Paypal'));
-            if ($directory->isExist($directory->getRelativePath($file))) {
+            if ($file && $directory->isExist($directory->getRelativePath($file))) {
                 $this->setTemplate($templateFile);
             } else {
                 $this->setTemplate('hss/iframe.phtml');
diff --git a/app/code/Magento/Paypal/Controller/Ipn/Index.php b/app/code/Magento/Paypal/Controller/Ipn/Index.php
index 6376122263a656d38e210f734422c19c3577fe75..ecf093e08ff25ccf7c10539d45eb7400fdcfe20f 100644
--- a/app/code/Magento/Paypal/Controller/Ipn/Index.php
+++ b/app/code/Magento/Paypal/Controller/Ipn/Index.php
@@ -22,8 +22,14 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
+
 namespace Magento\Paypal\Controller\Ipn;
 
+use \Magento\Paypal\UnavailableException;
+
+/**
+ * Unified IPN controller for all supported PayPal methods
+ */
 class Index extends \Magento\Framework\App\Action\Action
 {
     /**
@@ -65,8 +71,14 @@ class Index extends \Magento\Framework\App\Action\Action
         try {
             $data = $this->getRequest()->getPost();
             $this->_ipnFactory->create(array('data' => $data))->processIpnRequest();
+        } catch (UnavailableException $e) {
+            $this->_logger->logException($e);
+            $this->getResponse()->setHeader('HTTP/1.1', '503 Service Unavailable')->sendResponse();
+            /** @todo eliminate usage of exit statement */
+            exit;
         } catch (\Exception $e) {
             $this->_logger->logException($e);
+            $this->getResponse()->setHttpResponseCode(500);
         }
     }
 }
diff --git a/app/code/Magento/Paypal/Helper/Shortcut/Validator.php b/app/code/Magento/Paypal/Helper/Shortcut/Validator.php
index fdcc41231812da07b8a5b8dea68435fa540b23f1..11b96d814df367d18425d8c2df331756e0973326 100644
--- a/app/code/Magento/Paypal/Helper/Shortcut/Validator.php
+++ b/app/code/Magento/Paypal/Helper/Shortcut/Validator.php
@@ -118,7 +118,11 @@ class Validator implements ValidatorInterface
             $currentProduct = $this->_registry->registry('current_product');
             if (!is_null($currentProduct)) {
                 $productPrice = (double)$currentProduct->getFinalPrice();
-                if (empty($productPrice) && !$this->_productTypeConfig->isProductSet($currentProduct->getTypeId())) {
+                $typeInstance = $currentProduct->getTypeInstance();
+                if (empty($productPrice)
+                    && !$this->_productTypeConfig->isProductSet($currentProduct->getTypeId())
+                    && !$typeInstance->canConfigure($currentProduct)
+                ) {
                     return  false;
                 }
             }
diff --git a/app/code/Magento/Paypal/Model/AbstractIpn.php b/app/code/Magento/Paypal/Model/AbstractIpn.php
index 03fee1cce9f37913e089fd665e43229136dcd189..a05f8caba24f849b7d73457448062b6119046b3d 100644
--- a/app/code/Magento/Paypal/Model/AbstractIpn.php
+++ b/app/code/Magento/Paypal/Model/AbstractIpn.php
@@ -21,8 +21,11 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
+
 namespace Magento\Paypal\Model;
 
+use \Magento\Paypal\UnavailableException;
+
 class AbstractIpn
 {
     /**
@@ -113,6 +116,20 @@ class AbstractIpn
             throw $e;
         }
 
+        /*
+         * Handle errors on PayPal side.
+         */
+        $responseCode = \Zend_Http_Response::extractCode($postbackResult);
+        if (empty($postbackResult) || in_array($responseCode, array('500', '502', '503'))) {
+            if (empty($postbackResult)) {
+                $reason = 'Empty response.';
+            } else {
+                $reason = 'Response code: ' . $responseCode . '.';
+            }
+            $this->_debugData['exception'] = 'PayPal IPN postback failure. ' . $reason;
+            throw new UnavailableException($reason);
+        }
+
         $response = preg_split('/^\r?$/m', $postbackResult, 2);
         $response = trim($response[1]);
         if ($response != 'VERIFIED') {
diff --git a/app/code/Magento/Paypal/Model/Api/Nvp.php b/app/code/Magento/Paypal/Model/Api/Nvp.php
index 622f5969ea83659fe727e764c1abe52eb25dfbf4..37d9b1cd8ae624ba123d92149348999a9ed9e75b 100644
--- a/app/code/Magento/Paypal/Model/Api/Nvp.php
+++ b/app/code/Magento/Paypal/Model/Api/Nvp.php
@@ -770,6 +770,13 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi
      */
     protected $_curlFactory;
 
+    /**
+     * API call HTTP headers
+     *
+     * @var array
+     */
+    protected $_headers = array();
+
     /**
      * @param \Magento\Customer\Helper\Address $customerAddress
      * @param \Magento\Framework\Logger $logger
@@ -1156,24 +1163,30 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi
         return $request;
     }
 
-    /**
-     * Retrieve headers for request.
-     *
-     * @return array
-     */
-    protected function _getHeaderListForRequest()
-    {
-        return array();
-    }
-
     /**
      * Additional response processing.
+     * Hack to cut off length from API type response params.
      *
-     * @param  array $response
+     * @param array $response
      * @return array
      */
     protected function _postProcessResponse($response)
     {
+        foreach ($response as $key => $value) {
+            $pos = strpos($key, '[');
+
+            if ($pos === false) {
+                continue;
+            }
+
+            unset($response[$key]);
+
+            if ($pos !== 0) {
+                $modifiedKey = substr($key, 0, $pos);
+                $response[$modifiedKey] = $value;
+            }
+        }
+
         return $response;
     }
 
@@ -1212,7 +1225,7 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi
                 \Zend_Http_Client::POST,
                 $this->getApiEndpoint(),
                 '1.1',
-                $this->_getHeaderListForRequest(),
+                $this->_headers,
                 $this->_buildQuery($request)
             );
             $response = $http->read();
@@ -1364,7 +1377,7 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi
             $errorMessage = $this->_formatErrorMessage(
                 $errorCode,
                 $response["L_SHORTMESSAGE{$i}"],
-                $response["L_LONGMESSAGE{$i}"]
+                isset($response["L_LONGMESSAGE{$i}"]) ? $response["L_LONGMESSAGE{$i}"] : null
             );
             $errors[] = array (
                 'code' => $errorCode,
diff --git a/app/code/Magento/Paypal/Model/Api/PayflowNvp.php b/app/code/Magento/Paypal/Model/Api/PayflowNvp.php
index 7961ea26bb4e884d69b261fe46902ee7989a54ad..91efaed0555f7861e38c273a009d508c136212aa 100644
--- a/app/code/Magento/Paypal/Model/Api/PayflowNvp.php
+++ b/app/code/Magento/Paypal/Model/Api/PayflowNvp.php
@@ -101,6 +101,7 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
         'PWD' => 'password',
         'BUTTONSOURCE' => 'build_notation_code',
         'TENDER' => 'tender',
+
         // commands
         'RETURNURL' => 'return_url',
         'CANCELURL' => 'cancel_url',
@@ -110,6 +111,7 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
         'CUSTIP' => 'ip_address',
         'NOTIFYURL' => 'notify_url',
         'NOTE' => 'note',
+
         // style settings
         'PAGESTYLE' => 'page_style',
         'HDRIMG' => 'hdrimg',
@@ -120,15 +122,18 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
 
         // transaction info
         //We need to store paypal trx id for correct IPN working
+        'PPREF' => 'paypal_transaction_id',
         'PAYMENTINFO_0_TRANSACTIONID' => 'paypal_transaction_id',
         'TRANSACTIONID' => 'paypal_transaction_id',
         'REFUNDTRANSACTIONID' => 'paypal_transaction_id',
+
         'PNREF' => 'transaction_id',
         'ORIGID' => 'authorization_id',
         'CAPTURECOMPLETE' => 'complete_type',
         'AMT' => 'amount',
         'AVSADDR' => 'address_verification',
         'AVSZIP' => 'postcode_verification',
+
         // payment/billing info
         'CURRENCY' => 'currency_code',
         'PAYMENTSTATUS' => 'payment_status',
@@ -136,9 +141,11 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
         'PAYERID' => 'payer_id',
         'PAYERSTATUS' => 'payer_status',
         'EMAIL' => 'email',
+
         // backwards compatibility
         'FIRSTNAME' => 'firstname',
         'LASTNAME' => 'lastname',
+
         // paypal direct credit card information
         'ACCT' => 'credit_card_number',
         'EXPDATE' => 'credit_card_expiration_date',
@@ -146,6 +153,7 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
         'CARDSTART' => 'maestro_solo_issue_date',
         'CARDISSUE' => 'maestro_solo_issue_number',
         'CVV2MATCH' => 'cvv2_check_result',
+
         // cardinal centinel
         'AUTHSTATUS3DS' => 'centinel_authstatus',
         'MPIVENDOR3DS' => 'centinel_mpivendor',
@@ -198,7 +206,7 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
      */
     protected $_doDirectPaymentResponse = array(
         'PNREF',
-        'PAYMENTINFO_0_TRANSACTIONID',
+        'PPREF',
         'CORRELATIONID',
         'CVV2MATCH',
         'AVSADDR',
@@ -218,7 +226,7 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
      *
      * @var string[]
      */
-    protected $_doCaptureResponse = array('PNREF', 'TRANSACTIONID');
+    protected $_doCaptureResponse = array('PNREF', 'PPREF');
 
     /**
      * DoVoid request map
@@ -246,7 +254,7 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
      *
      * @var string[]
      */
-    protected $_refundTransactionResponse = array('PNREF', 'REFUNDTRANSACTIONID');
+    protected $_refundTransactionResponse = array('PNREF', 'PPREF');
 
     /**
      * SetExpressCheckout request map
@@ -306,7 +314,7 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
      */
     protected $_doExpressCheckoutPaymentResponse = array(
         'PNREF',
-        'PAYMENTINFO_0_TRANSACTIONID',
+        'PPREF',
         'REPMSG',
         'AMT',
         'PENDINGREASON',
@@ -408,9 +416,9 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
      * @var array
      */
     protected $_lineItemExportItemsFormat = array(
-        'name' => 'L_PAYMENTREQUEST_%d_NAME%d',
-        'qty' => 'L_PAYMENTREQUEST_%d_QTY%d',
-        'amount' => 'L_PAYMENTREQUEST_%d_AMT%d'
+        'name' => 'L_NAME%d',
+        'qty' => 'L_QTY%d',
+        'amount' => 'L_COST%d'
     );
 
     /**
@@ -435,7 +443,7 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
      * @var array
      */
     protected $_requiredResponseParams = array(
-        self::DO_DIRECT_PAYMENT => array('RESULT', 'PNREF', 'PAYMENTINFO_0_TRANSACTIONID')
+        self::DO_DIRECT_PAYMENT => array('RESULT', 'PNREF', 'PPREF')
     );
 
     /**
@@ -443,6 +451,11 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
      */
     protected $mathRandom;
 
+    /**
+     * @var NvpFactory
+     */
+    protected $nvpFactory;
+
     /**
      * @param \Magento\Customer\Helper\Address $customerAddress
      * @param \Magento\Framework\Logger $logger
@@ -454,6 +467,7 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
      * @param \Magento\Framework\Model\ExceptionFactory $frameworkExceptionFactory
      * @param \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory
      * @param \Magento\Framework\Math\Random $mathRandom
+     * @param NvpFactory $nvpFactory
      * @param array $data
      */
     public function __construct(
@@ -467,6 +481,7 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
         \Magento\Framework\Model\ExceptionFactory $frameworkExceptionFactory,
         \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory,
         \Magento\Framework\Math\Random $mathRandom,
+        NvpFactory $nvpFactory,
         array $data = array()
     ) {
         parent::__construct(
@@ -482,6 +497,7 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
             $data
         );
         $this->mathRandom = $mathRandom;
+        $this->nvpFactory = $nvpFactory;
     }
 
     /**
@@ -731,17 +747,6 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
         return $requestFields;
     }
 
-    /**
-     * Retrieve headers for request.
-     * This is a hack to make Payflow work with negative values for items like discount has.
-     *
-     * @return string[]
-     */
-    protected function _getHeaderListForRequest()
-    {
-        return array('PAYPAL-NVP: Y');
-    }
-
     /**
      * Additional response processing.
      * Hack to cut off length from API type response params.
@@ -770,73 +775,55 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
     }
 
     /**
-     * Prepare line items request.
-     * Returns true if there were line items added.
+     * Checking negative line items
      *
-     * @param array &$request
+     * @param array $request
      * @param int $i
-     * @return bool|null
+     * @return null|true
      */
     protected function _exportLineItems(array &$request, $i = 0)
     {
-        return $this->_preparePaymentRequestLineItems($request, 0, $i);
+        $requestBefore = $request;
+        $result = parent::_exportLineItems($request, $i);
+        if ($this->getIsLineItemsEnabled() && $this->_cart->hasNegativeItemAmount()) {
+            $this->_lineItemTotalExportMap = array(
+                Cart::AMOUNT_TAX      => 'TAXAMT',
+                Cart::AMOUNT_SHIPPING => 'FREIGHTAMT',
+                'amount'              => 'PAYMENTREQUEST_0_ITEMAMT',
+            );
+            $this->_lineItemExportItemsFormat = array(
+                'name'   => 'L_PAYMENTREQUEST_0_NAME%d',
+                'qty'    => 'L_PAYMENTREQUEST_0_QTY%d',
+                'amount' => 'L_PAYMENTREQUEST_0_AMT%d',
+            );
+            $request = $requestBefore;
+            $result = parent::_exportLineItems($request, $i);
+            /** @var Nvp $paypalNvp */
+            $paypalNvp = $this->nvpFactory->create();
+            $this->_doCaptureResponse = $paypalNvp->_doCaptureResponse;
+            $this->_refundTransactionResponse = $paypalNvp->_refundTransactionResponse;
+            $this->_getTransactionDetailsResponse = $paypalNvp->_getTransactionDetailsResponse;
+            $this->_paymentInformationResponse = $paypalNvp->_paymentInformationResponse;
+            $this->_headers[] = 'PAYPAL-NVP: Y';
+            $this->_setSpecificForNegativeLineItems();
+        }
+        return $result;
     }
 
     /**
-     * NVP doesn't support passing discount total as a separate amount - add it as a line item.
-     * This is a hack for proper line items display for order at PP EC side using Payflow through API.
-     *
-     * @param array &$request
-     * @param int $requestNum
-     * @param int $itemNum
-     * @return bool|null
-     * @link https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_nvp_r_SetExpressCheckout
+     * Set specific data when negative line item case
+     * @return void
      */
-    protected function _preparePaymentRequestLineItems(array &$request, $requestNum = 0, $itemNum = 0)
+    protected function _setSpecificForNegativeLineItems()
     {
-        if (!$this->_cart) {
-            return;
-        }
-
-        $this->_cart->setTransferDiscountAsItem();
-
-        // always add cart totals, even if line items are not requested
-        if ($this->_lineItemTotalExportMap) {
-            foreach ($this->_cart->getAmounts() as $key => $total) {
-                if (isset($this->_lineItemTotalExportMap[$key])) {
-                    // !empty($total)
-                    $privateKey = $this->_lineItemTotalExportMap[$key];
-                    $request[$privateKey] = $this->_filterAmount($total);
-                } elseif (isset($this->_lineItemsExportRequestTotalsFormat[$key])) {
-                    $privateKey = sprintf($this->_lineItemsExportRequestTotalsFormat[$key], $requestNum);
-                    $request[$privateKey] = $this->_filterAmount($total);
-                }
-            }
+        /** @var Nvp $paypalNvp */
+        $paypalNvp = $this->nvpFactory->create();
+        $this->_setExpressCheckoutResponse = $paypalNvp->_setExpressCheckoutResponse;
+        $index = array_search('PPREF', $this->_doExpressCheckoutPaymentResponse);
+        if (false !== $index) {
+            unset($this->_doExpressCheckoutPaymentResponse[$index]);
         }
-
-        // add cart line items
-        $items = $this->_cart->getAllItems();
-        if (empty($items) || !$this->getIsLineItemsEnabled()) {
-            return;
-        }
-
-        $result = null;
-        foreach ($items as $item) {
-            foreach ($this->_lineItemExportItemsFormat as $publicKey => $privateFormat) {
-                $result = true;
-                $value = $item->getDataUsingMethod($publicKey);
-                if (isset($this->_lineItemExportItemsFilters[$publicKey])) {
-                    $callback = $this->_lineItemExportItemsFilters[$publicKey];
-                    $value = call_user_func(array($this, $callback), $value);
-                }
-                if (is_float($value)) {
-                    $value = $this->_filterAmount($value);
-                }
-                $request[sprintf($privateFormat, $requestNum, $itemNum)] = $value;
-            }
-            $itemNum++;
-        }
-
-        return $result;
+        $this->_doExpressCheckoutPaymentResponse[] = 'PAYMENTINFO_0_TRANSACTIONID';
+        $this->_requiredResponseParams[self::DO_EXPRESS_CHECKOUT_PAYMENT][] = 'PAYMENTINFO_0_TRANSACTIONID';
     }
 }
diff --git a/app/code/Magento/Paypal/Model/Cart.php b/app/code/Magento/Paypal/Model/Cart.php
index 7fd5a6b01a96c2db4054c8c6c22193b9bac39758..30c2cdb0dbc967795160e9ac6451081dbb256084 100644
--- a/app/code/Magento/Paypal/Model/Cart.php
+++ b/app/code/Magento/Paypal/Model/Cart.php
@@ -197,4 +197,19 @@ class Cart extends \Magento\Payment\Model\Cart
         $this->addTax((double)$dataContainer->getBaseHiddenTaxAmount());
         $this->addTax((double)$dataContainer->getBaseShippingHiddenTaxAmnt());
     }
+
+    /**
+     * Check whether any item has negative amount
+     *
+     * @return bool
+     */
+    public function hasNegativeItemAmount()
+    {
+        foreach ($this->_customItems as $item) {
+            if ($item->getAmount() < 0) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/app/code/Magento/Paypal/Model/Express/Checkout.php b/app/code/Magento/Paypal/Model/Express/Checkout.php
index b3ca649ad73f3993ca5514bcfb2e4145aefa36d9..83bf85995421fb62f067b75780ce64a84d2b6e38 100644
--- a/app/code/Magento/Paypal/Model/Express/Checkout.php
+++ b/app/code/Magento/Paypal/Model/Express/Checkout.php
@@ -686,14 +686,10 @@ class Checkout
             $billingAddress = $quote->getBillingAddress();
         }
         $exportedBillingAddress = $this->_api->getExportedBillingAddress();
-        $quote->setCustomerEmail($billingAddress->getEmail());
-        $quote->setCustomerPrefix($billingAddress->getPrefix());
-        $quote->setCustomerFirstname($billingAddress->getFirstname());
-        $quote->setCustomerMiddlename($billingAddress->getMiddlename());
-        $quote->setCustomerLastname($billingAddress->getLastname());
-        $quote->setCustomerSuffix($billingAddress->getSuffix());
-        $quote->setCustomerNote($exportedBillingAddress->getData('note'));
+
         $this->_setExportedAddressData($billingAddress, $exportedBillingAddress);
+        $billingAddress->setCustomerNote($exportedBillingAddress->getData('note'));
+        $quote->setBillingAddress($billingAddress);
 
         // import payment info
         $payment = $quote->getPayment();
diff --git a/app/code/Magento/Paypal/Model/Hostedpro/Request.php b/app/code/Magento/Paypal/Model/Hostedpro/Request.php
index ca185bc878e364592e38e4220f14fcb44fbad44f..3de3ef174f050f7320dae86779eb0f72353aa25d 100644
--- a/app/code/Magento/Paypal/Model/Hostedpro/Request.php
+++ b/app/code/Magento/Paypal/Model/Hostedpro/Request.php
@@ -208,11 +208,12 @@ class Request extends \Magento\Framework\Object
      */
     protected function _getShippingAddress(\Magento\Framework\Object $address)
     {
+        $region = $address->getRegionCode() ? $address->getRegionCode() : $address->getRegion();
         $request = array(
             'first_name' => $address->getFirstname(),
             'last_name' => $address->getLastname(),
             'city' => $address->getCity(),
-            'state' => $address->getRegionCode() ? $address->getRegionCode() : $address->getCity(),
+            'state' => $region ? $region : $address->getCity(),
             'zip' => $address->getPostcode(),
             'country' => $address->getCountry()
         );
@@ -234,11 +235,12 @@ class Request extends \Magento\Framework\Object
      */
     protected function _getBillingAddress(\Magento\Framework\Object $address)
     {
+        $region = $address->getRegionCode() ? $address->getRegionCode() : $address->getRegion();
         $request = array(
             'billing_first_name' => $address->getFirstname(),
             'billing_last_name' => $address->getLastname(),
             'billing_city' => $address->getCity(),
-            'billing_state' => $address->getRegionCode() ? $address->getRegionCode() : $address->getCity(),
+            'billing_state' => $region ? $region : $address->getCity(),
             'billing_zip' => $address->getPostcode(),
             'billing_country' => $address->getCountry()
         );
diff --git a/app/code/Magento/Paypal/Model/Ipn.php b/app/code/Magento/Paypal/Model/Ipn.php
index 493bd9bdee3d3ee827f3fb010c316f313345a001..e871ca462aa007f41425cedc9afba8b6a1c71e16 100644
--- a/app/code/Magento/Paypal/Model/Ipn.php
+++ b/app/code/Magento/Paypal/Model/Ipn.php
@@ -229,7 +229,7 @@ class Ipn extends \Magento\Paypal\Model\AbstractIpn implements IpnInterface
             switch ($paymentStatus) {
                 // paid
                 case Info::PAYMENTSTATUS_COMPLETED:
-                    $this->_registerPaymentCapture();
+                    $this->_registerPaymentCapture(true);
                     break;
                     // the holded payment was denied on paypal side
                 case Info::PAYMENTSTATUS_DENIED:
@@ -274,29 +274,38 @@ class Ipn extends \Magento\Paypal\Model\AbstractIpn implements IpnInterface
     /**
      * Process completed payment (either full or partial)
      *
+     * @param bool $skipFraudDetection
      * @return void
      */
-    protected function _registerPaymentCapture()
+    protected function _registerPaymentCapture($skipFraudDetection = false)
     {
         if ($this->getRequestData('transaction_entity') == 'auth') {
             return;
         }
+        $parentTransactionId = $this->getRequestData('parent_txn_id');
         $this->_importPaymentInformation();
         $payment = $this->_order->getPayment();
         $payment->setTransactionId(
             $this->getRequestData('txn_id')
-        )->setCurrencyCode(
+        );
+        $payment->setCurrencyCode(
             $this->getRequestData('mc_currency')
-        )->setPreparedMessage(
+        );
+        $payment->setPreparedMessage(
             $this->_createIpnComment('')
-        )->setParentTransactionId(
-            $this->getRequestData('parent_txn_id')
-        )->setShouldCloseParentTransaction(
+        );
+        $payment->setParentTransactionId(
+            $parentTransactionId
+        );
+        $payment->setShouldCloseParentTransaction(
             'Completed' === $this->getRequestData('auth_status')
-        )->setIsTransactionClosed(
+        );
+        $payment->setIsTransactionClosed(
             0
-        )->registerCaptureNotification(
-            $this->getRequestData('mc_gross')
+        );
+        $payment->registerCaptureNotification(
+            $this->getRequestData('mc_gross'),
+            $skipFraudDetection && $parentTransactionId
         );
         $this->_order->save();
 
@@ -360,7 +369,9 @@ class Ipn extends \Magento\Paypal\Model\AbstractIpn implements IpnInterface
             throw new Exception('The "order" authorizations are not implemented.');
         }
         // case when was placed using PayPal standard
-        if (\Magento\Sales\Model\Order::STATE_PENDING_PAYMENT == $this->_order->getState()) {
+        if (\Magento\Sales\Model\Order::STATE_PENDING_PAYMENT == $this->_order->getState()
+            && !$this->getRequestData('transaction_entity')
+        ) {
             $this->_registerPaymentCapture();
             return;
         }
@@ -399,6 +410,8 @@ class Ipn extends \Magento\Paypal\Model\AbstractIpn implements IpnInterface
                 $this->getRequestData('txn_id')
             )->setParentTransactionId(
                 $this->getRequestData('parent_txn_id')
+            )->setCurrencyCode(
+                $this->getRequestData('mc_currency')
             )->setIsTransactionClosed(
                 0
             )->registerAuthorizationNotification(
diff --git a/app/code/Magento/Paypal/Model/Method/Agreement.php b/app/code/Magento/Paypal/Model/Method/Agreement.php
index 2aa41c4c3ce140058fac69ccea19318e4863c1e8..cc2e0d474b06efe2e508f25d6949bf09478cab65 100644
--- a/app/code/Magento/Paypal/Model/Method/Agreement.php
+++ b/app/code/Magento/Paypal/Model/Method/Agreement.php
@@ -87,14 +87,14 @@ class Agreement extends \Magento\Paypal\Model\Payment\Method\Billing\AbstractAgr
      *
      * @var bool
      */
-    protected $_canUseCheckout = false;
+    protected $_canUseCheckout = true;
 
     /**
      * Method instance setting
      *
      * @var bool
      */
-    protected $_canUseInternal = false;
+    protected $_canUseInternal = true;
 
     /**
      * Method instance setting
diff --git a/app/code/Magento/Paypal/Model/Method/Checks/SpecificationPlugin.php b/app/code/Magento/Paypal/Model/Method/Checks/SpecificationPlugin.php
new file mode 100644
index 0000000000000000000000000000000000000000..7da69fe6c039f4c899981f311f9cc709bf6325b6
--- /dev/null
+++ b/app/code/Magento/Paypal/Model/Method/Checks/SpecificationPlugin.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Paypal\Model\Method\Checks;
+
+use Magento\Payment\Model\Checks\PaymentMethodChecksInterface;
+use Magento\Sales\Model\Quote;
+use Magento\Payment\Model\Checks\SpecificationInterface;
+use Magento\Paypal\Model\Billing\AgreementFactory;
+
+class SpecificationPlugin
+{
+    /**
+     * @var AgreementFactory
+     */
+    protected $_agreementFactory;
+
+    /**
+     * @param AgreementFactory $agreementFactory
+     */
+    public function __construct(AgreementFactory $agreementFactory)
+    {
+        $this->_agreementFactory = $agreementFactory;
+    }
+
+    /**
+     * Override check for Billing Agreements
+     *
+     * @param SpecificationInterface $specification
+     * @param \Closure $proceed
+     * @param PaymentMethodChecksInterface $paymentMethod
+     * @param Quote $quote
+     * @return bool
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function aroundIsApplicable(
+        SpecificationInterface $specification,
+        \Closure $proceed,
+        PaymentMethodChecksInterface $paymentMethod,
+        Quote $quote
+    ) {
+        $originallyIsApplicable = $proceed($paymentMethod, $quote);
+        if (!$originallyIsApplicable || $paymentMethod->getCode() != 'paypal_billing_agreement'
+            || !$quote->getCustomerId()
+        ) {
+            return $originallyIsApplicable;
+        }
+        $availableBA = $this->_agreementFactory->create()->getAvailableCustomerBillingAgreements(
+            $quote->getCustomerId()
+        );
+        return count($availableBA) > 0;
+    }
+}
diff --git a/app/code/Magento/Paypal/Model/Payflowlink.php b/app/code/Magento/Paypal/Model/Payflowlink.php
index 989980c6f452c76c1655d13ce5820a0881e581ec..31b9354b080bbd9bc09c633ff05afc4c32ceea78 100644
--- a/app/code/Magento/Paypal/Model/Payflowlink.php
+++ b/app/code/Magento/Paypal/Model/Payflowlink.php
@@ -156,6 +156,7 @@ class Payflowlink extends \Magento\Paypal\Model\Payflowpro
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
      * @param \Magento\Paypal\Model\ConfigFactory $configFactory
      * @param \Magento\Framework\Math\Random $mathRandom
+     * @param \Magento\Framework\HTTP\ZendClientFactory $httpClientFactory
      * @param \Magento\Paypal\Model\Payflow\RequestFactory $requestFactory
      * @param \Magento\Sales\Model\QuoteFactory $quoteFactory
      * @param \Magento\Sales\Model\OrderFactory $orderFactory
@@ -177,6 +178,7 @@ class Payflowlink extends \Magento\Paypal\Model\Payflowpro
         \Magento\Store\Model\StoreManagerInterface $storeManager,
         \Magento\Paypal\Model\ConfigFactory $configFactory,
         \Magento\Framework\Math\Random $mathRandom,
+        \Magento\Framework\HTTP\ZendClientFactory $httpClientFactory,
         \Magento\Paypal\Model\Payflow\RequestFactory $requestFactory,
         \Magento\Sales\Model\QuoteFactory $quoteFactory,
         \Magento\Sales\Model\OrderFactory $orderFactory,
@@ -201,6 +203,7 @@ class Payflowlink extends \Magento\Paypal\Model\Payflowpro
             $storeManager,
             $configFactory,
             $mathRandom,
+            $httpClientFactory,
             $data
         );
     }
diff --git a/app/code/Magento/Paypal/Model/Payflowpro.php b/app/code/Magento/Paypal/Model/Payflowpro.php
index 2a08c4e4c308f2bcb575b220d86b5de4a1048af8..9e4be498b697bac1691fc74aa829483a8ecac28d 100644
--- a/app/code/Magento/Paypal/Model/Payflowpro.php
+++ b/app/code/Magento/Paypal/Model/Payflowpro.php
@@ -47,6 +47,12 @@ class Payflowpro extends \Magento\Payment\Model\Method\Cc
 
     const TRXTYPE_DELAYED_INQUIRY = 'I';
 
+    const TRXTYPE_ACCEPT_DENY       = 'U';
+
+    const UPDATEACTION_APPROVED = 'APPROVE';
+
+    const UPDATEACTION_DECLINED_BY_MERCHANT = 'FPS_MERCHANT_DECLINE';
+
     /**
      * Tender type codes
      */
@@ -171,6 +177,13 @@ class Payflowpro extends \Magento\Payment\Model\Method\Cc
      */
     protected $_canFetchTransactionInfo = true;
 
+    /**
+     * Payment Method feature
+     *
+     * @var bool
+     */
+    protected $_canReviewPayment = true;
+
     /**
      * Gateway request timeout
      *
@@ -213,6 +226,11 @@ class Payflowpro extends \Magento\Payment\Model\Method\Cc
      */
     protected $mathRandom;
 
+    /**
+     * @var \Magento\Framework\HTTP\ZendClientFactory
+     */
+    protected $_httpClientFactory;
+
     /**
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Payment\Helper\Data $paymentData
@@ -225,6 +243,7 @@ class Payflowpro extends \Magento\Payment\Model\Method\Cc
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
      * @param \Magento\Paypal\Model\ConfigFactory $configFactory
      * @param \Magento\Framework\Math\Random $mathRandom
+     * @param \Magento\Framework\HTTP\ZendClientFactory $httpClientFactory
      * @param array $data
      *
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
@@ -241,11 +260,13 @@ class Payflowpro extends \Magento\Payment\Model\Method\Cc
         \Magento\Store\Model\StoreManagerInterface $storeManager,
         \Magento\Paypal\Model\ConfigFactory $configFactory,
         \Magento\Framework\Math\Random $mathRandom,
+        \Magento\Framework\HTTP\ZendClientFactory $httpClientFactory,
         array $data = array()
     ) {
         $this->_storeManager = $storeManager;
         $this->_configFactory = $configFactory;
         $this->mathRandom = $mathRandom;
+        $this->_httpClientFactory = $httpClientFactory;
         parent::__construct(
             $eventManager,
             $paymentData,
@@ -479,6 +500,7 @@ class Payflowpro extends \Magento\Payment\Model\Method\Cc
     {
         $request = $this->_buildBasicRequest($payment);
         $request->setTrxtype(self::TRXTYPE_DELAYED_INQUIRY);
+        $transactionId = $payment->getCcTransId() ? $payment->getCcTransId() : $transactionId;
         $request->setOrigid($transactionId);
         $response = $this->_postRequest($request);
 
@@ -537,7 +559,8 @@ class Payflowpro extends \Magento\Payment\Model\Method\Cc
     {
         $debugData = array('request' => $request->getData());
 
-        $client = new \Magento\Framework\HTTP\ZendClient();
+        /** @var \Magento\Framework\HTTP\ZendClient $client */
+        $client = $this->_httpClientFactory->create();
         $result = new \Magento\Framework\Object();
 
         $_config = array('maxredirects' => 5, 'timeout' => 30, 'verifypeer' => $this->getConfigData('verify_peer'));
@@ -630,7 +653,15 @@ class Payflowpro extends \Magento\Payment\Model\Method\Cc
             $request->setCurrency($order->getBaseCurrencyCode());
 
             $orderIncrementId = $order->getIncrementId();
-            $request->setCustref($orderIncrementId)->setComment1($orderIncrementId);
+
+            $request->setCurrency($order->getBaseCurrencyCode())
+                ->setInvnum($orderIncrementId)
+                ->setPonum($order->getId())
+                ->setComment1($orderIncrementId);
+            $customerId = $order->getCustomerId();
+            if ($customerId) {
+                $request->setCustref($customerId);
+            }
 
             $billing = $order->getBillingAddress();
             if (!empty($billing)) {
@@ -731,6 +762,8 @@ class Payflowpro extends \Magento\Payment\Model\Method\Cc
             $response->getResultCode() != self::RESPONSE_CODE_FRAUDSERVICE_FILTER
         ) {
             throw new \Magento\Framework\Model\Exception($response->getRespmsg());
+        } elseif ($response->getOrigresult() == self::RESPONSE_CODE_FRAUDSERVICE_FILTER) {
+            throw new \Magento\Framework\Model\Exception($response->getRespmsg());
         }
     }
 
@@ -745,4 +778,58 @@ class Payflowpro extends \Magento\Payment\Model\Method\Cc
     {
         return $this;
     }
+
+    /**
+     * Attempt to accept a pending payment
+     *
+     * @param \Magento\Payment\Model\Info $payment
+     * @return bool
+     */
+    public function acceptPayment(\Magento\Payment\Model\Info $payment)
+    {
+        return $this->reviewPayment($payment, self::UPDATEACTION_APPROVED);
+    }
+
+    /**
+     * Attempt to deny a pending payment
+     *
+     * @param \Magento\Payment\Model\Info $payment
+     * @return bool
+     */
+    public function denyPayment(\Magento\Payment\Model\Info $payment)
+    {
+        return $this->reviewPayment($payment, self::UPDATEACTION_DECLINED_BY_MERCHANT);
+    }
+
+
+    /**
+     * Perform the payment review
+     *
+     * @param \Magento\Payment\Model\Info $payment
+     * @param string $action
+     * @return bool
+     */
+    public function reviewPayment(\Magento\Payment\Model\Info $payment, $action)
+    {
+        $request = $this->_buildBasicRequest($payment);
+        $transactionId = ($payment->getCcTransId()) ? $payment->getCcTransId() : $payment->getLastTransId();
+        $request->setTrxtype(self::TRXTYPE_ACCEPT_DENY);
+        $request->setOrigid($transactionId);
+        $request->setUpdateaction($action);
+
+        $response = $this->_postRequest($request);
+        $payment->setAdditionalInformation((array)$response->getData());
+        $this->_processErrors($response);
+
+        if (!$this->_isTransactionUnderReview($response->getOrigresult())) {
+            $payment->setTransactionId($response->getOrigpnref())->setIsTransactionClosed(0);
+            if ($response->getOrigresult() == self::RESPONSE_CODE_APPROVED) {
+                $payment->setIsTransactionApproved(true);
+            } else if ($response->getOrigresult() == self::RESPONSE_CODE_DECLINED_BY_MERCHANT) {
+                $payment->setIsTransactionDenied(true);
+            }
+        }
+        $rawData = $response->getData();
+        return ($rawData) ? $rawData : array();
+    }
 }
diff --git a/app/code/Magento/Paypal/Model/Payment/Method/Billing/AbstractAgreement.php b/app/code/Magento/Paypal/Model/Payment/Method/Billing/AbstractAgreement.php
index fa9970603fb453c1132eb0b7c7f0be90239552bb..312cff117bd5d4c495243cf3be2730340a449abf 100644
--- a/app/code/Magento/Paypal/Model/Payment/Method/Billing/AbstractAgreement.php
+++ b/app/code/Magento/Paypal/Model/Payment/Method/Billing/AbstractAgreement.php
@@ -86,13 +86,6 @@ abstract class AbstractAgreement extends \Magento\Payment\Model\Method\AbstractM
     public function isAvailable($quote = null)
     {
         if (is_null($this->_isAvailable)) {
-            if (is_object($quote) && $quote->getCustomerId()) {
-                $availableBA = $this->_agreementFactory->create()->getAvailableCustomerBillingAgreements(
-                    $quote->getCustomerId()
-                );
-                $isAvailableBA = count($availableBA) > 0;
-                $this->_canUseCheckout = $this->_canUseInternal = $isAvailableBA;
-            }
             $this->_isAvailable = parent::isAvailable($quote) && $this->_isAvailable($quote);
             $this->_canUseCheckout = $this->_isAvailable && $this->_canUseCheckout;
             $this->_canUseInternal = $this->_isAvailable && $this->_canUseInternal;
diff --git a/app/code/Magento/Paypal/Model/Report/Settlement.php b/app/code/Magento/Paypal/Model/Report/Settlement.php
index c5f84e716051569245c1d83ca3d22780c9d0c303..642ca200ae531c25b03c92473d9fa2e2a95c45fd 100644
--- a/app/code/Magento/Paypal/Model/Report/Settlement.php
+++ b/app/code/Magento/Paypal/Model/Report/Settlement.php
@@ -133,7 +133,8 @@ class Settlement extends \Magento\Framework\Model\AbstractModel
                 'Fee Currency' => 13,
                 'Custom Field' => 14,
                 'Consumer ID' => 15,
-                'Payment Tracking ID' => 16
+                'Payment Tracking ID' => 16,
+                'Store ID' => 17
             ),
             'rowmap' => array(
                 'Transaction ID' => 'transaction_id',
@@ -151,7 +152,8 @@ class Settlement extends \Magento\Framework\Model\AbstractModel
                 'Fee Currency' => 'fee_currency',
                 'Custom Field' => 'custom_field',
                 'Consumer ID' => 'consumer_id',
-                'Payment Tracking ID' => 'payment_tracking_id'
+                'Payment Tracking ID' => 'payment_tracking_id',
+                'Store ID' => 'store_id'
             )
         )
     );
@@ -246,8 +248,11 @@ class Settlement extends \Magento\Framework\Model\AbstractModel
 
                 $encoded = $this->_tmpDirectory->readFile($localCsv);
                 $csvFormat = 'new';
-                if (self::FILES_OUT_CHARSET != mb_detect_encoding($encoded)) {
-                    $decoded = @iconv(self::FILES_IN_CHARSET, self::FILES_OUT_CHARSET . '//IGNORE', $encoded);
+
+                $fileEncoding = mb_detect_encoding($encoded);
+
+                if (self::FILES_OUT_CHARSET != $fileEncoding) {
+                    $decoded = @iconv($fileEncoding, self::FILES_OUT_CHARSET.'//IGNORE', $encoded);
                     $this->_tmpDirectory->writeFile($localCsv, $decoded);
                     $csvFormat = 'old';
                 }
diff --git a/app/code/Magento/Paypal/UnavailableException.php b/app/code/Magento/Paypal/UnavailableException.php
new file mode 100644
index 0000000000000000000000000000000000000000..6b4c9e9124eadfedc0f325236acb78b6843544fe
--- /dev/null
+++ b/app/code/Magento/Paypal/UnavailableException.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+ 
+namespace Magento\Paypal;
+
+/**
+ * Class UnavailableException for exceptions on Paypal side
+ * @package Magento\Paypal
+ */
+class UnavailableException extends \Magento\Framework\Model\Exception
+{
+
+}
diff --git a/app/code/Magento/Paypal/etc/di.xml b/app/code/Magento/Paypal/etc/di.xml
index 7acdb23682d0aae630d5ab4dcbf70808367503a4..4fc299e88f13d35c7069ae3605066acc18bd5c46 100644
--- a/app/code/Magento/Paypal/etc/di.xml
+++ b/app/code/Magento/Paypal/etc/di.xml
@@ -76,6 +76,9 @@
             <argument name="alias" xsi:type="string">product.info.addtocart.paypalbml</argument>
         </arguments>
     </type>
+    <type name="Magento\Payment\Model\Checks\Composite">
+        <plugin name="paypal_specification" type="Magento\Paypal\Model\Method\Checks\SpecificationPlugin"/>
+    </type>
     <virtualType name="Magento\Paypal\Block\Payflow\Bml\Shortcut" type="Magento\Paypal\Block\Bml\Shortcut">
         <arguments>
             <argument name="paymentMethodCode" xsi:type="const">Magento\Paypal\Model\Config::METHOD_WPP_PE_EXPRESS</argument>
diff --git a/app/code/Magento/Paypal/etc/frontend/di.xml b/app/code/Magento/Paypal/etc/frontend/di.xml
index 5b7dbd8539dcd723b2ccbf000a7bb1d288e70926..7605fb374383c548cc7a72802ddc5332cf5bfe9c 100644
--- a/app/code/Magento/Paypal/etc/frontend/di.xml
+++ b/app/code/Magento/Paypal/etc/frontend/di.xml
@@ -58,6 +58,8 @@
                 <item name="paypal_payflowexpress" xsi:type="string">/paypal/payflowexpress</item>
                 <item name="paypal_standard" xsi:type="string">/paypal/standard</item>
                 <item name="paypal_express_callbackshippingoptions" xsi:type="string">paypal/express/callbackshippingoptions</item>
+                <item name="paypal_bml" xsi:type="string">/paypal/bml</item>
+                <item name="paypal_payflowbml" xsi:type="string">/paypal/payflowbml</item>
             </argument>
         </arguments>
     </type>
diff --git a/app/code/Magento/Paypal/etc/module.xml b/app/code/Magento/Paypal/etc/module.xml
index a15d87db0015667e74bcd738f18e960a618ac103..228996c72b5e40fb408ac462a85cdefeb903a19d 100644
--- a/app/code/Magento/Paypal/etc/module.xml
+++ b/app/code/Magento/Paypal/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Paypal" schema_version="1.6.0.3" active="true">
+    <module name="Magento_Paypal" schema_version="1.6.0.4" active="true">
         <sequence>
             <module name="Magento_Checkout"/>
             <module name="Magento_Sales"/>
diff --git a/app/code/Magento/Paypal/etc/payment.xml b/app/code/Magento/Paypal/etc/payment.xml
index ca6074525cba356b17b5c293c9af777626d4244b..2302478cf066f1b01fe62f573c24e6a77253bdc1 100644
--- a/app/code/Magento/Paypal/etc/payment.xml
+++ b/app/code/Magento/Paypal/etc/payment.xml
@@ -41,8 +41,6 @@
     <methods>
         <method name="paypal_express">
             <support_recurring_payment>1</support_recurring_payment>
-            <allow_multiple_address>1</allow_multiple_address>
-            <allow_multiple_with_3dsecure>1</allow_multiple_with_3dsecure>
         </method>
         <method name="paypal_direct">
             <allow_multiple_address>1</allow_multiple_address>
@@ -50,15 +48,9 @@
         </method>
         <method name="paypal_billing_agreement">
             <allow_multiple_address>1</allow_multiple_address>
-            <allow_multiple_with_3dsecure>1</allow_multiple_with_3dsecure>
         </method>
         <method name="payflow_express">
-            <allow_multiple_address>1</allow_multiple_address>
-            <allow_multiple_with_3dsecure>1</allow_multiple_with_3dsecure>
-        </method>
-        <method name="payflow_advanced">
-            <allow_multiple_address>1</allow_multiple_address>
-            <allow_multiple_with_3dsecure>1</allow_multiple_with_3dsecure>
+            <support_recurring_payment>1</support_recurring_payment>        
         </method>
         <method name="payflowpro">
             <allow_multiple_address>1</allow_multiple_address>
diff --git a/app/code/Magento/Paypal/sql/paypal_setup/upgrade-1.6.0.3-1.6.0.4.php b/app/code/Magento/Paypal/sql/paypal_setup/upgrade-1.6.0.3-1.6.0.4.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ab3222b039ddd83eb65a1b1d8580cdb59964ca2
--- /dev/null
+++ b/app/code/Magento/Paypal/sql/paypal_setup/upgrade-1.6.0.3-1.6.0.4.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/** @var $installer \Magento\Sales\Model\Resource\Setup */
+$installer = $this;
+
+$installer->getConnection()
+    ->addColumn(
+        $installer->getTable('paypal_settlement_report_row'),
+        'store_id',
+        array(
+            'type'    => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
+            'comment' => 'Store ID',
+            'length'  => '50'
+        )
+    );
diff --git a/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml b/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml
index 8945271ff782230416ddf06d4906971352e6f7c7..85ffa6aa7d78131741fb5e5eaf5355933e561bfb 100644
--- a/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml
+++ b/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml
@@ -23,8 +23,8 @@
  */
 ?>
 <?php /* @var $this \Magento\Paypal\Block\Billing\Agreement\View */ ?>
-<div class="block billing agreements">
-    <div class="title">
+<div class="block block-billing-agreements-view">
+    <div class="block-title">
         <strong><?php echo __('Billing Agreement # %1', $this->escapeHtml($this->getReferenceId())) ?></strong>
         <?php if ($this->getCanCancel()): ?>
             <button type="button" title="<?php echo __('Cancel') ?>" class="secondary action cancel" onclick="if( confirm('<?php echo __('Are you sure you want to do this?') ?>') ) { window.location.href = '<?php echo $this->getCancelUrl() ?>'; } return false;">
@@ -32,31 +32,31 @@
             </button>
         <?php endif; ?>
     </div>
-    <div class="content">
-        <h2 class="subtitle caption"><?php echo __('Agreement Information') ?></h2>
-        <div class="wrapper table billing agreements">
-            <table class="data table">
+    <div class="block-title"><strong><?php echo __('Agreement Information') ?></strong></div>
+    <div class="block-content">
+        <div class="table-wrapper billing-agreements-view">
+            <table class="data table table-billing-agreements-view">
                 <caption class="table caption"><?php echo __('Agreement Information') ?></caption>
                 <thead>
                     <tr>
-                        <th class="col id"><?php echo __('Reference ID:'); ?></th>
-                        <th class="col status"><?php echo __('Status:'); ?></th>
-                        <th class="col created"><?php echo __('Created:'); ?></th>
+                        <th scope="col" class="col id"><?php echo __('Reference ID:'); ?></th>
+                        <th scope="col" class="col status"><?php echo __('Status:'); ?></th>
+                        <th scope="col" class="col created"><?php echo __('Created:'); ?></th>
                         <?php if($this->getAgreementUpdatedAt()): ?>
-                            <th class="col updated"><?php echo __('Updated:'); ?></th>
+                            <th scope="col" class="col updated"><?php echo __('Updated:'); ?></th>
                         <?php endif; ?>
-                        <th class="col payment"><?php echo __('Payment Method:'); ?></th>
+                        <th scope="col" class="col payment"><?php echo __('Payment Method:'); ?></th>
                     </tr>
                 </thead>
                 <tbody>
                     <tr>
-                        <td class="col id"><?php echo $this->escapeHtml($this->getReferenceId()); ?></td>
-                        <td class="col status"><?php echo $this->getAgreementStatus() ?></td>
-                        <td class="col created"><?php echo $this->escapeHtml($this->getAgreementCreatedAt()) ?></td>
+                        <td data-th="<?php echo $this->escapeHtml(__('Reference ID:')); ?>" class="col id"><?php echo $this->escapeHtml($this->getReferenceId()); ?></td>
+                        <td data-th="<?php echo $this->escapeHtml(__('Status:')); ?>" class="col status"><?php echo $this->getAgreementStatus() ?></td>
+                        <td data-th="<?php echo $this->escapeHtml(__('Created:')); ?>" class="col created"><?php echo $this->escapeHtml($this->getAgreementCreatedAt()) ?></td>
                         <?php if($this->getAgreementUpdatedAt()): ?>
-                            <td class="col updated"><?php echo $this->escapeHtml($this->getAgreementUpdatedAt()); ?></td>
+                            <td data-th="<?php echo $this->escapeHtml(__('Updated:')); ?>" class="col updated"><?php echo $this->escapeHtml($this->getAgreementUpdatedAt()); ?></td>
                         <?php endif; ?>
-                        <td class="col payment"><?php echo $this->getPaymentMethodTitle() ?></td>
+                        <td data-th="<?php echo $this->escapeHtml(__('Payment Method:')); ?>" class="col payment"><?php echo $this->getPaymentMethodTitle() ?></td>
                     </tr>
                 </tbody>
             </table>
@@ -65,32 +65,35 @@
         <?php if(count($relatedOrders) > 0): ?>
         <?php echo $this->getChildHtml('pager'); ?>
         <h2 class="subtitle caption"><?php echo __('Related Orders') ?></h2>
-        <table class="data table" id="related-orders-table">
-            <thead>
-                <tr>
-                    <th class="col id"><?php echo __('Order #') ?></th>
-                    <th class="col date"><?php echo __('Date') ?></th>
-                    <th class="col shipto"><?php echo __('Ship To') ?></th>
-                    <th class="col total"><?php echo __('Order Total') ?></th>
-                    <th class="col status"><?php echo __('Order Status') ?></th>
-                    <th class="col actions">&nbsp;</th>
-                </tr>
-            </thead>
-            <tbody>
-            <?php foreach ($relatedOrders as $order): ?>
-                <tr>
-                    <th class="col id"><?php echo $this->getOrderItemValue($order, 'order_increment_id') ?></th>
-                    <th class="col date"><?php echo $this->getOrderItemValue($order, 'created_at') ?></th>
-                    <th class="col shipto"><?php echo $this->getOrderItemValue($order, 'shipping_address') ?></th>
-                    <th class="col total"><?php echo $this->getOrderItemValue($order, 'order_total') ?></th>
-                    <th class="col status"><?php echo $this->getOrderItemValue($order, 'status_label') ?></th>
-                    <th class="col actions">
-                        <a href="<?php echo $this->getOrderItemValue($order, 'view_url') ?>"><?php echo __('View Order') ?></a>
-                    </th>
-                </tr>
-            <?php endforeach; ?>
-            </tbody>
-        </table>
+        <div class="table-wrapper billing-agreements-related">
+            <table class="data table table-billing-agreements-related" id="related-orders-table">
+                <caption class="table caption"><?php echo __('Related Orders') ?></caption>
+                <thead>
+                    <tr>
+                        <th scope="col" class="col id"><?php echo __('Order #') ?></th>
+                        <th scope="col" class="col date"><?php echo __('Date') ?></th>
+                        <th scope="col" class="col shipto"><?php echo __('Ship To') ?></th>
+                        <th scope="col" class="col total"><?php echo __('Order Total') ?></th>
+                        <th scope="col" class="col status"><?php echo __('Order Status') ?></th>
+                        <th scope="col" class="col actions">&nbsp;</th>
+                    </tr>
+                </thead>
+                <tbody>
+                <?php foreach ($relatedOrders as $order): ?>
+                    <tr>
+                        <th data-th="<?php echo $this->escapeHtml(__('Order #')); ?>" class="col id"><?php echo $this->getOrderItemValue($order, 'order_increment_id') ?></th>
+                        <th data-th="<?php echo $this->escapeHtml(__('Date')); ?>" class="col date"><?php echo $this->getOrderItemValue($order, 'created_at') ?></th>
+                        <th data-th="<?php echo $this->escapeHtml(__('Ship To')); ?>" class="col shipto"><?php echo $this->getOrderItemValue($order, 'shipping_address') ?></th>
+                        <th data-th="<?php echo $this->escapeHtml(__('Order Total')); ?>" class="col total"><?php echo $this->getOrderItemValue($order, 'order_total') ?></th>
+                        <th data-th="<?php echo $this->escapeHtml(__('Order Status')); ?>" class="col status"><?php echo $this->getOrderItemValue($order, 'status_label') ?></th>
+                        <th data-th="" class="col actions">
+                            <a href="<?php echo $this->getOrderItemValue($order, 'view_url') ?>"><?php echo __('View Order') ?></a>
+                        </th>
+                    </tr>
+                <?php endforeach; ?>
+                </tbody>
+            </table>
+        </div>
         <?php endif; ?>
 
         <div class="actions-toolbar">
diff --git a/app/code/Magento/Paypal/view/frontend/templates/billing/agreements.phtml b/app/code/Magento/Paypal/view/frontend/templates/billing/agreements.phtml
index 6420a0acc12f4f6b199fa7751f9719187e0a6542..84b1ff4917ac5abd03031de6775e0dce885f1909 100644
--- a/app/code/Magento/Paypal/view/frontend/templates/billing/agreements.phtml
+++ b/app/code/Magento/Paypal/view/frontend/templates/billing/agreements.phtml
@@ -23,32 +23,32 @@
  */
 ?>
 <?php /* @var $this \Magento\Paypal\Block\Billing\Agreements */ ?>
-<div class="block billing agreements">
+<div class="account-billing-agreements">
     <?php $billingAgreements = $this->getBillingAgreements(); ?>
     <?php if (count($billingAgreements) > 0): ?>
         <?php echo $this->getChildHtml('pager'); ?>
-        <div class="wrapper table billing agreements">
-            <table id="billing-agreements" class="data table billing agreements">
+        <div class="table-wrapper billing-agreements">
+            <table id="billing-agreements" class="data table table-billing-agreements">
                 <caption class="table caption"><?php echo __('Billing Agreements') ?></caption>
                 <thead>
                 <tr>
-                    <th class="col id"><?php echo __('Reference ID'); ?></th>
-                    <th class="col status"><?php echo __('Status'); ?></th>
-                    <th class="col created"><?php echo __('Created At'); ?></th>
-                    <th class="col updated"><?php echo __('Updated At'); ?></th>
-                    <th class="col payment"><?php echo __('Payment Method'); ?></th>
-                    <th class="col actions">&nbsp;</th>
+                    <th scope="col" class="col id"><?php echo __('Reference ID'); ?></th>
+                    <th scope="col" class="col status"><?php echo __('Status'); ?></th>
+                    <th scope="col" class="col created"><?php echo __('Created At'); ?></th>
+                    <th scope="col" class="col updated"><?php echo __('Updated At'); ?></th>
+                    <th scope="col" class="col payment"><?php echo __('Payment Method'); ?></th>
+                    <th scope="col" class="col actions">&nbsp;</th>
                 </tr>
                 </thead>
                 <tbody>
                 <?php foreach ($billingAgreements as $item): ?>
                     <tr>
-                        <td class="col id"><?php echo $this->getItemValue($item, 'reference_id') ?></td>
-                        <td class="col status"><?php echo $this->getItemValue($item, 'status') ?></td>
-                        <td class="col created"><?php echo $this->getItemValue($item, 'created_at') ?></td>
-                        <td class="col updated"><?php echo $this->getItemValue($item, 'updated_at') ?></td>
-                        <td class="col payment"><?php echo $this->getItemValue($item, 'payment_method_label') ?></td>
-                        <td class="col actions">
+                        <td data-th="<?php echo $this->escapeHtml(__('Reference ID')); ?>" class="col id"><?php echo $this->getItemValue($item, 'reference_id') ?></td>
+                        <td data-th="<?php echo $this->escapeHtml(__('Status')); ?>" class="col status"><?php echo $this->getItemValue($item, 'status') ?></td>
+                        <td data-th="<?php echo $this->escapeHtml(__('Created At')); ?>" class="col created"><?php echo $this->getItemValue($item, 'created_at') ?></td>
+                        <td data-th="<?php echo $this->escapeHtml(__('Updated At')); ?>" class="col updated"><?php echo $this->getItemValue($item, 'updated_at') ?></td>
+                        <td data-th="<?php echo $this->escapeHtml(__('Payment Method')); ?>" class="col payment"><?php echo $this->getItemValue($item, 'payment_method_label') ?></td>
+                        <td data-th="" class="col actions">
                             <a href="<?php echo $this->getItemValue($item, 'edit_url') ?>"><?php echo __('View') ?></a>
                         </td>
                     </tr>
@@ -62,10 +62,10 @@
 
     <?php $paymentMethods = $this->getWizardPaymentMethodOptions() ?>
     <?php if ($paymentMethods): ?>
-        <h2 class="subtitle caption"><?php echo __('New Billing Agreement') ?></h2>
-
-        <form action="<?php echo $this->getCreateUrl() ?>" method="post" class="form new agreement">
+        <form action="<?php echo $this->getCreateUrl() ?>" method="post" class="form form-new-agreement">
             <fieldset class="fieldset">
+                <legend class="legend"><span><?php echo __('New Billing Agreement') ?></span></legend>
+                <br />
                 <p class="note"><?php echo __('You will be redirected to the payment system website.') ?></p>
 
                 <div class="field payment method">
diff --git a/app/code/Magento/RecurringPayment/view/frontend/templates/recurring/grid.phtml b/app/code/Magento/RecurringPayment/view/frontend/templates/recurring/grid.phtml
index 4a5774eaa063acbfb273583ae59ce9d6c8742c0d..34a92266f32108e4ed6a9b4acc86c5f173e302cf 100644
--- a/app/code/Magento/RecurringPayment/view/frontend/templates/recurring/grid.phtml
+++ b/app/code/Magento/RecurringPayment/view/frontend/templates/recurring/grid.phtml
@@ -32,45 +32,53 @@
 
     <?php $gridElements = $this->getGridElements(); ?>
     <?php if ($gridElements): ?>
-        <div class="toolbar"><?php echo $this->getChildHtml('pager'); ?></div>
-        <table id="<?php echo $this->getGridHtmlId() ?>" class="data table">
-            <thead>
-            <tr>
-                <?php foreach ($this->getGridColumns() as $column):
-                    $nobr = $this->getObjectData($column, 'is_nobr') ? '<span class="nobr">%s</span>' : '%s';
-                    $title = $this->getObjectData($column, 'title');
-                    ?>
-                    <th class="col title"><?php echo $title ? sprintf($nobr, $this->escapeHtml($title)) : '&nbsp;' ?></th>
-                <?php endforeach; ?>
-            </tr>
-            </thead>
-            <tbody>
-            <?php foreach ($gridElements as $row): ?>
+        <?php if ($this->getChildHtml('pager')): ?>
+            <div class="toolbar recurring-payments-toolbar top"><?php echo $this->getChildHtml('pager'); ?></div>
+        <?php endif; ?>
+        <div class="table-wrapper recurring-payments">
+            <table id="<?php echo $this->getGridHtmlId() ?>" class="data table table-recurring-payments">
+                <caption class="table caption"><?php echo __('Recurring Payments') ?></caption>
+                <thead>
                 <tr>
                     <?php foreach ($this->getGridColumns() as $column):
-                        $nobr = $this->getObjectData($column, 'is_nobr') ? '<span class="nobr">%s</span>' : '%s';
-                        $index = $this->getObjectData($column, 'index');
-                        $value = $this->getObjectData($row, $index);
-                        $linkUrl = $this->getObjectData($row, "{$index}_link_url");
-                        $linkAnchorText = $this->getObjectData($row, "{$index}_link_text");
-                        $linkText = $linkUrl ? ($linkAnchorText ? $linkAnchorText : $value) : '';
-                        $linkFormat = $linkUrl ? '<a href="%s">%s</a>' : '';
+                        $nobr = $this->getObjectData($column, 'is_nobr') ? '<span>%s</span>' : '%s';
+                        $title = $this->getObjectData($column, 'title');
                         ?>
-                        <td<?php echo $this->getObjectData($row, 'is_amount') ? ' class="col qty"' : '' ?>>
-                            <?php
-                            if ($linkFormat) {
-                                echo sprintf($nobr, sprintf($linkFormat, $this->escapeHtml($linkUrl), $this->escapeHtml($linkText)));
-                            } else {
-                                echo sprintf($nobr, $this->escapeHtml($value));
-                            }
-                            ?>
-                        </td>
+                        <th scope="col" class="col title"><?php echo $title ? sprintf($nobr, $this->escapeHtml($title)) : '&nbsp;' ?></th>
                     <?php endforeach; ?>
                 </tr>
-            <?php endforeach; ?>
-            </tbody>
-        </table>
-        <div class="toolbar"><?php echo $this->getChildHtml('pager'); ?></div>
+                </thead>
+                <tbody>
+                <?php foreach ($gridElements as $row): ?>
+                    <tr>
+                        <?php foreach ($this->getGridColumns() as $column):
+                            $nobr = $this->getObjectData($column, 'is_nobr') ? '<span>%s</span>' : '%s';
+                            $index = $this->getObjectData($column, 'index');
+                            $value = $this->getObjectData($row, $index);
+                            $linkUrl = $this->getObjectData($row, "{$index}_link_url");
+                            $linkAnchorText = $this->getObjectData($row, "{$index}_link_text");
+                            $linkText = $linkUrl ? ($linkAnchorText ? $linkAnchorText : $value) : '';
+                            $linkFormat = $linkUrl ? '<a href="%s">%s</a>' : '';
+                            $title = $this->getObjectData($column, 'title');
+                            ?>
+                            <td data-th="<?php echo $title ? $this->escapeHtml($title) : '&nbsp;' ?>" <?php echo $this->getObjectData($row, 'is_amount') ? ' class="col qty"' : '' ?>>
+                                <?php
+                                if ($linkFormat) {
+                                    echo sprintf($nobr, sprintf($linkFormat, $this->escapeHtml($linkUrl), $this->escapeHtml($linkText)));
+                                } else {
+                                    echo sprintf($nobr, $this->escapeHtml($value));
+                                }
+                                ?>
+                            </td>
+                        <?php endforeach; ?>
+                    </tr>
+                <?php endforeach; ?>
+                </tbody>
+            </table>
+        </div>
+        <?php if ($this->getChildHtml('pager')): ?>
+            <div class="toolbar recurring-payments-toolbar bottom"><?php echo $this->getChildHtml('pager'); ?></div>
+        <?php endif;?>
     <?php else: ?>
         <div class="message info empty"><span><?php echo $this->escapeHtml($this->getEmptyGridMessage()); ?></span></div>
     <?php endif; ?>
diff --git a/app/code/Magento/Reports/Model/Resource/Report/Collection/AbstractCollection.php b/app/code/Magento/Reports/Model/Resource/Report/Collection/AbstractCollection.php
index bc7f79e9eea275f7fb7b83d42135b2d7919915d3..70c1a8954a0e5cfdf7ffeeaac48d79117a182de3 100644
--- a/app/code/Magento/Reports/Model/Resource/Report/Collection/AbstractCollection.php
+++ b/app/code/Magento/Reports/Model/Resource/Report/Collection/AbstractCollection.php
@@ -129,6 +129,16 @@ class AbstractCollection extends \Magento\Framework\Model\Resource\Db\Collection
         return $this;
     }
 
+    /**
+     * Apply needed aggregated table
+     *
+     * @return $this
+     */
+    protected function _applyAggregatedTable()
+    {
+        return $this;
+    }
+
     /**
      * Apply date range filter
      *
@@ -257,6 +267,7 @@ class AbstractCollection extends \Magento\Framework\Model\Resource\Db\Collection
     {
         parent::_beforeLoad();
 
+        $this->_applyAggregatedTable();
         $this->_applyDateRangeFilter();
         $this->_applyStoresFilter();
         $this->_applyCustomFilter();
diff --git a/app/code/Magento/Review/Block/Adminhtml/Product/Grid.php b/app/code/Magento/Review/Block/Adminhtml/Product/Grid.php
index b49f4457f359cc2bdf1eb2369e7d72f7d27a6bfe..a5d7d8990fe90a1af04359a4c847d6746147ee42 100644
--- a/app/code/Magento/Review/Block/Adminhtml/Product/Grid.php
+++ b/app/code/Magento/Review/Block/Adminhtml/Product/Grid.php
@@ -159,7 +159,7 @@ class Grid extends \Magento\Catalog\Block\Adminhtml\Product\Grid
      */
     public function getGridUrl()
     {
-        return $this->getUrl('catalog/product/productGrid', array('_current' => true));
+        return $this->getUrl('review/product/productGrid', array('_current' => true));
     }
 
     /**
diff --git a/app/code/Magento/Review/Block/Product/Review.php b/app/code/Magento/Review/Block/Product/Review.php
new file mode 100644
index 0000000000000000000000000000000000000000..ed15320b73b5f80424b46aa427665d63912df5ca
--- /dev/null
+++ b/app/code/Magento/Review/Block/Product/Review.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Review\Block\Product;
+
+use Magento\Review\Model\Resource\Review\Collection as ReviewCollection;
+
+/**
+ * Product Review Tab
+ *
+ * @author     Magento Core Team <core@magentocommerce.com>
+ */
+class Review extends \Magento\Framework\View\Element\Template
+{
+    /**
+     * Core registry
+     *
+     * @var \Magento\Framework\Registry
+     */
+    protected $_coreRegistry;
+
+    /**
+     * Review resource model
+     *
+     * @var \Magento\Review\Model\Resource\Review\CollectionFactory
+     */
+    protected $_reviewsColFactory;
+
+    /**
+     * @param \Magento\Backend\Block\Template\Context $context
+     * @param \Magento\Framework\Registry $registry
+     * @param \Magento\Review\Model\Resource\Review\CollectionFactory $collectionFactory
+     * @param array $data
+     */
+    public function __construct(
+        \Magento\Backend\Block\Template\Context $context,
+        \Magento\Framework\Registry $registry,
+        \Magento\Review\Model\Resource\Review\CollectionFactory $collectionFactory,
+        array $data = array()
+    ) {
+
+        $this->_coreRegistry = $registry;
+        $this->_reviewsColFactory = $collectionFactory;
+        parent::__construct($context, $data);
+
+        $this->setTabTitle();
+    }
+
+    /**
+     * Get current product id
+     *
+     * @return null|int
+     */
+    public function getProductId()
+    {
+        $product = $this->_coreRegistry->registry('product');
+        return $product ? $product->getId() : null;
+    }
+
+    /**
+     * Get URL for ajax call
+     *
+     * @return string
+     */
+    public function getProductReviewUrl()
+    {
+        return $this->getUrl('review/product/listAjax', array('id' => $this->getProductId()));
+    }
+
+    /**
+     * Set tab title
+     *
+     * @return void
+     */
+    public function setTabTitle()
+    {
+        $title = $this->getCollectionSize()
+            ? __('Reviews %1', '<span class="counter">' . $this->getCollectionSize() . '</span>')
+            : __('Reviews');
+        $this->setTitle($title);
+    }
+
+    /**
+     * Get size of reviews collection
+     *
+     * @return int
+     */
+    public function getCollectionSize()
+    {
+        $collection = $this->_reviewsColFactory->create()->addStoreFilter(
+            $this->_storeManager->getStore()->getId()
+        )->addStatusFilter(
+            \Magento\Review\Model\Review::STATUS_APPROVED
+        )->addEntityFilter(
+            'product',
+            $this->getProductId()
+        );
+
+        return $collection->getSize();
+    }
+}
diff --git a/app/code/Magento/Review/Block/Product/ReviewRenderer.php b/app/code/Magento/Review/Block/Product/ReviewRenderer.php
index 822c017a3aa3eba0e16927bb70d24bcc403ec422..39010e82308e0b685fcc85dc8035dc610909c267 100644
--- a/app/code/Magento/Review/Block/Product/ReviewRenderer.php
+++ b/app/code/Magento/Review/Block/Product/ReviewRenderer.php
@@ -118,13 +118,18 @@ class ReviewRenderer extends \Magento\Framework\View\Element\Template implements
     /**
      * Get review product list url
      *
+     * @param bool $useDirectLink allows to use direct link for product reviews page
      * @return string
      */
-    public function getReviewsUrl()
+    public function getReviewsUrl($useDirectLink = false)
     {
-        return $this->getUrl(
-            'review/product/list',
-            array('id' => $this->getProduct()->getId(), 'category' => $this->getProduct()->getCategoryId())
-        );
+        $product = $this->getProduct();
+        if ($useDirectLink) {
+            return $this->getUrl(
+                'review/product/list',
+                array('id' => $product->getId(), 'category' => $product->getCategoryId())
+            );
+        }
+        return $product->getUrlModel()->getUrl($product, array('_ignore_category' => true));
     }
 }
diff --git a/app/code/Magento/Review/Block/Product/View.php b/app/code/Magento/Review/Block/Product/View.php
index 5fc7f0e2bc93760a47e0fd8697f6cc84ad91c6c0..418c4a0ed41b0de8df6695fbee1f8b002e4b686e 100644
--- a/app/code/Magento/Review/Block/Product/View.php
+++ b/app/code/Magento/Review/Block/Product/View.php
@@ -52,7 +52,6 @@ class View extends \Magento\Catalog\Block\Product\View
      * @param \Magento\Core\Helper\Data $coreData
      * @param \Magento\Framework\Json\EncoderInterface $jsonEncoder
      * @param \Magento\Catalog\Model\ProductFactory $productFactory
-     * @param \Magento\Tax\Model\Calculation $taxCalculation
      * @param \Magento\Framework\Stdlib\String $string
      * @param \Magento\Catalog\Helper\Product $productHelper
      * @param \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig
@@ -67,7 +66,6 @@ class View extends \Magento\Catalog\Block\Product\View
         \Magento\Core\Helper\Data $coreData,
         \Magento\Framework\Json\EncoderInterface $jsonEncoder,
         \Magento\Catalog\Model\ProductFactory $productFactory,
-        \Magento\Tax\Model\Calculation $taxCalculation,
         \Magento\Framework\Stdlib\String $string,
         \Magento\Catalog\Helper\Product $productHelper,
         \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig,
@@ -83,7 +81,6 @@ class View extends \Magento\Catalog\Block\Product\View
             $coreData,
             $jsonEncoder,
             $productFactory,
-            $taxCalculation,
             $string,
             $productHelper,
             $productTypeConfig,
diff --git a/app/code/Magento/Review/Controller/Product/ListAjax.php b/app/code/Magento/Review/Controller/Product/ListAjax.php
new file mode 100644
index 0000000000000000000000000000000000000000..67095da81bbefa119f32ca1487c2dbda4ab9b2c8
--- /dev/null
+++ b/app/code/Magento/Review/Controller/Product/ListAjax.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ *
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Review\Controller\Product;
+
+class ListAjax extends \Magento\Review\Controller\Product
+{
+    /**
+     * Show list of product's reviews
+     *
+     * @return void
+     */
+    public function execute()
+    {
+        $this->_initProduct();
+        $this->_view->loadLayout();
+        $this->_view->renderLayout();
+    }
+}
diff --git a/app/code/Magento/Review/view/frontend/layout/catalog_product_view.xml b/app/code/Magento/Review/view/frontend/layout/catalog_product_view.xml
index f9b4f8c6d5d4d24214bb73944ccf94cc3f4ee87a..263f6ff4274b02ee4479183b2ef4f53a2e1e2773 100644
--- a/app/code/Magento/Review/view/frontend/layout/catalog_product_view.xml
+++ b/app/code/Magento/Review/view/frontend/layout/catalog_product_view.xml
@@ -33,4 +33,11 @@
             </arguments>
         </block>
     </referenceContainer>
+    <referenceBlock name="product.info.details">
+        <block class="Magento\Review\Block\Product\Review" name="reviews.tab" as="reviews" template="Magento_Review::review.phtml" group="detailed_info">
+            <block class="Magento\Review\Block\Form" name="product.review.form" as="review_form" cacheable="false">
+                <container name="product.review.form.fields.before" as="form_fields_before" label="Review Form Fields Before"/>
+            </block>
+        </block>
+    </referenceBlock>
 </layout>
diff --git a/app/code/Magento/Review/view/frontend/layout/review_product_listajax.xml b/app/code/Magento/Review/view/frontend/layout/review_product_listajax.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2c0d767ee8ebfd92104469e5d1831d08253bb25d
--- /dev/null
+++ b/app/code/Magento/Review/view/frontend/layout/review_product_listajax.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Core/etc/layout_single.xsd">
+    <remove name="root"/>
+    <block class="Magento\Review\Block\Product\View\ListView" name="product.info.product_additional_data" as="product_additional_data" template="product/view/list.phtml" output="1"/>
+    <block class="Magento\Theme\Block\Html\Pager" name="product_review_list.toolbar" output="1">
+        <arguments>
+            <argument name="show_per_page" xsi:type="boolean">false</argument>
+            <argument name="show_amounts" xsi:type="boolean">false</argument>
+        </arguments>
+    </block>
+</layout>
diff --git a/app/code/Magento/Review/view/frontend/templates/customer/list.phtml b/app/code/Magento/Review/view/frontend/templates/customer/list.phtml
index e4c77558dd9404a431d601e6735c323a56745ebc..e7ec66e27540915a03bab7dfe8b0d50f57e7acf6 100644
--- a/app/code/Magento/Review/view/frontend/templates/customer/list.phtml
+++ b/app/code/Magento/Review/view/frontend/templates/customer/list.phtml
@@ -23,44 +23,46 @@
  */
 ?>
 <?php if( $this->getCollection() && $this->count()): ?>
-    <div class="products toolbar reviews">
-        <?php echo $this->getToolbarHtml() ?>
-    </div>
-    <div class="wrapper table reviews">
-        <table class="data table reviews" id="my-reviews-table">
+    <?php if ($this->getToolbarHtml()): ?>
+        <div class="toolbar products-reviews-toolbar top">
+            <?php echo $this->getToolbarHtml() ?>
+        </div>
+    <?php endif; ?>
+    <div class="table-wrapper reviews">
+        <table class="data table table-reviews" id="my-reviews-table">
             <caption class="table caption"><?php echo __('Product Reviews') ?></caption>
             <thead>
                 <tr>
-                    <th class="col date"><?php echo __('Created') ?></th>
-                    <th class="col item"><?php echo __('Product Name') ?></th>
-                    <th class="col summary"><?php echo __('Summary') ?></th>
-                    <th class="col description"><?php echo __('Description') ?></th>
-                    <th class="col actions">&nbsp;</th>
+                    <th scope="col" class="col date"><?php echo __('Created') ?></th>
+                    <th scope="col" class="col item"><?php echo __('Product Name') ?></th>
+                    <th scope="col" class="col summary"><?php echo __('Rating') ?></th>
+                    <th scope="col" class="col description"><?php echo __('Review') ?></th>
+                    <th scope="col" class="col actions">&nbsp;</th>
                 </tr>
             </thead>
             <tbody>
                 <?php foreach ($this->getCollection() as $_review): ?>
                 <tr>
-                    <td class="col date"><?php echo $this->dateFormat($_review->getReviewCreatedAt()); ?></td>
-                    <td class="col item">
-                        <strong class="product name">
+                    <td data-th="<?php echo $this->escapeHtml(__('Created')) ?>" class="col date"><?php echo $this->dateFormat($_review->getReviewCreatedAt()); ?></td>
+                    <td data-th="<?php echo $this->escapeHtml(__('Product Name')) ?>" class="col item">
+                        <strong class="product-name">
                             <a href="<?php echo $this->getProductLink() ?>id/<?php echo $_review->getEntityPkValue() ?>"><?php echo $this->escapeHtml($_review->getName()) ?></a>
                         </strong>
                     </td>
-                    <td class="col summary">
+                    <td data-th="<?php echo $this->escapeHtml(__('Rating')) ?>" class="col summary">
                     <?php if($_review->getSum()): ?>
-                        <div class="rating summary">
+                        <div class="rating-summary">
                             <span class="label"><span><?php echo __('Rating') ?>:</span></span>
-                            <div class="rating result" title="<?php echo ( $_review->getSum() / $_review->getCount() ) ?>%">
+                            <div class="rating-result" title="<?php echo ( $_review->getSum() / $_review->getCount() ) ?>%">
                                 <span style="width:<?php echo ( $_review->getSum() / $_review->getCount() ) ?>%;"><span><?php echo ( $_review->getSum() / $_review->getCount() ) ?>%</span></span>
                             </div>
                         </div>
                     <?php endif; ?>
                     </td>
-                    <td class="col description">
+                    <td data-th="<?php echo $this->escapeHtml(__('Review')) ?>" class="col description">
                         <?php echo $this->helper('Magento\Review\Helper\Data')->getDetailHtml($_review->getDetail()) ?>
                     </td>
-                    <td class="col actions">
+                    <td data-th="" class="col actions">
                         <a href="<?php echo $this->getReviewLink() ?>id/<?php echo $_review->getReviewId() ?>" class="action more">
                             <span><?php echo __('View Details') ?></span>
                         </a>
@@ -70,9 +72,11 @@
             </tbody>
         </table>
     </div>
-    <div class="products toolbar reviews bottom">
-        <?php echo $this->getToolbarHtml() ?>
-    </div>
+    <?php if ($this->getToolbarHtml()): ?>
+        <div class="toolbar products-reviews-toolbar bottom">
+            <?php echo $this->getToolbarHtml() ?>
+        </div>
+    <?php endif; ?>
 <?php else: ?>
     <div class="message info empty"><span><?php echo __('You have submitted no reviews.') ?></span></div>
 <?php endif; ?>
diff --git a/app/code/Magento/Review/view/frontend/templates/customer/recent.phtml b/app/code/Magento/Review/view/frontend/templates/customer/recent.phtml
index 962210d341c6e38cc6d325d115b35bb3384fa0a9..f9b95885b07f7dbf9171e61d5992d62f552aa5dd 100644
--- a/app/code/Magento/Review/view/frontend/templates/customer/recent.phtml
+++ b/app/code/Magento/Review/view/frontend/templates/customer/recent.phtml
@@ -28,21 +28,21 @@
 ?>
 
 <?php if( $this->getCollection() && $this->count()): ?>
-<div class="block reviews dashboard">
-    <div class="title">
+<div class="block block-reviews-dashboard">
+    <div class="block-title">
         <strong><?php echo __('My Recent Reviews') ?></strong>
-        <a class="action view" href="<?php echo $this->getAllReviewsUrl() ?>"><span><?php echo __('View All Reviews') ?></span></a>
+        <a class="action view" href="<?php echo $this->getAllReviewsUrl() ?>"><span><?php echo __('View All') ?></span></a>
     </div>
-    <div class="content">
+    <div class="block-content">
         <ol class="items">
         <?php foreach ($this->getCollection() as $_review): ?>
             <li class="item">
-                <strong class="product name"><a href="<?php echo $this->getReviewUrl($_review->getReviewId()) ?>"><?php echo $this->escapeHtml($_review->getName()) ?></a></strong>
+                <strong class="product-name"><a href="<?php echo $this->getReviewUrl($_review->getReviewId()) ?>"><?php echo $this->escapeHtml($_review->getName()) ?></a></strong>
                 <?php if($_review->getSum()): ?>
                 <?php $rating = $_review->getSum() / $_review->getCount() ?>
-                    <div class="rating summary">
+                    <div class="rating-summary">
                          <span class="label"><span><?php echo __('Rating') ?>:</span></span>
-                         <div class="rating result" title="<?php echo $rating; ?>%">
+                         <div class="rating-result" title="<?php echo $rating; ?>%">
                              <span style="width:<?php echo $rating; ?>%"><span><?php echo $rating; ?>%</span></span>
                          </div>
                      </div>
diff --git a/app/code/Magento/Review/view/frontend/templates/customer/view.phtml b/app/code/Magento/Review/view/frontend/templates/customer/view.phtml
index 79f513333492d595b153470769a20603df230250..9914b5407b72f3d3cb5a7d90713b8dff48581c15 100644
--- a/app/code/Magento/Review/view/frontend/templates/customer/view.phtml
+++ b/app/code/Magento/Review/view/frontend/templates/customer/view.phtml
@@ -24,49 +24,50 @@
 ?>
 <?php if($this->getProductData()->getId()): ?>
 <?php $imageBlock =  $this->getLayout()->createBlock('Magento\Catalog\Block\Product\Image'); ?>
-<div class="customer review view">
-    <h2 class="product name"><?php echo $this->escapeHtml($this->getProductData()->getName()) ?></h2>
-    <div class="product details">
-        <a class="product photo" href="<?php echo $this->getProductData()->getProductUrl() ?>">
-            <?php /* customer_account_product_review_page */ ?>
-            <?php echo $imageBlock->init($this->getProductData(), 'customer_account_product_review_page')->toHtml() ?>
-        </a>
-        <?php if( $this->getRating() && $this->getRating()->getSize()): ?>
-        <p><?php echo __('Average Customer Rating:') ?></p>
-        <?php echo $this->getReviewsSummaryHtml($this->getProductData()) ?>
-        <?php endif; ?>
+<div class="customer-review view">
+    <div class="product-details">
+        <div class="product-media">
+            <a class="product-photo" href="<?php echo $this->getProductData()->getProductUrl() ?>">
+                <?php /* customer_account_product_review_page */ ?>
+                <?php echo $imageBlock->init($this->getProductData(), 'customer_account_product_review_page')->toHtml() ?>
+            </a>
+        </div>
+        <div class="product-info">
+            <h2 class="product-name"><?php echo $this->escapeHtml($this->getProductData()->getName()) ?></h2>
+            <?php if( $this->getRating() && $this->getRating()->getSize()): ?>
+                <span class="rating-average-label"><?php echo __('Average Customer Rating:') ?></span>
+                <?php echo $this->getReviewsSummaryHtml($this->getProductData()) ?>
+            <?php endif; ?>
+        </div>
     </div>
-    <div class="review details">
 
+    <div class="review-details">
         <?php if( $this->getRating() && $this->getRating()->getSize()): ?>
-        <div class="ratings summary items">
-            <strong><?php echo ($this->isReviewOwner()) ? __('Your Rating:') : __('Rating:'); ?></strong>
-
-            <?php foreach ($this->getRating() as $_rating): ?>
-            <?php if($_rating->getPercent()): ?>
-                <?php $rating = ceil($_rating->getPercent()) ?>
-                <div class="rating summary item">
-                    <span class="label"><span><?php echo $this->escapeHtml($_rating->getRatingCode()) ?>:</span></span>
-                    <div class="rating result" title="<?php echo $rating; ?>%">
-                        <span style="width:<?php echo $rating; ?>%">
-                            <span><?php echo $rating; ?>%</span>
-                        </span>
+            <div class="title">
+                <strong><?php echo ($this->isReviewOwner()) ? __('Your Review') : __('Review'); ?></strong>
+            </div>
+            <div class="customer-review-rating">
+                <?php foreach ($this->getRating() as $_rating): ?>
+                <?php if($_rating->getPercent()): ?>
+                    <?php $rating = ceil($_rating->getPercent()) ?>
+                    <div class="rating-summary item">
+                        <span class="rating-label"><span><?php echo $this->escapeHtml($_rating->getRatingCode()) ?></span></span>
+                        <div class="rating-result" title="<?php echo $rating; ?>%">
+                            <span style="width:<?php echo $rating; ?>%">
+                                <span><?php echo $rating; ?>%</span>
+                            </span>
+                        </div>
                     </div>
-                </div>
-            <?php endif; ?>
-            <?php endforeach; ?>
-        </div>
+                <?php endif; ?>
+                <?php endforeach; ?>
+            </div>
         <?php endif; ?>
 
-        <div class="review title"><?php echo $this->escapeHtml($this->getReviewData()->getTitle()) ?></div>
-        <p class="review date">
-            <?php if ($this->isReviewOwner()): ?>
-                <?php echo __('Your Review (submitted on %1):', '<time class="date">' . $this->dateFormat($this->getReviewData()->getCreatedAt()) . '</time>') ?>
-            <?php else :?>
-                <?php echo __('Review (submitted on %1):', '<time class="date">' . $this->dateFormat($this->getReviewData()->getCreatedAt()) . '</time>') ?>
-            <?php endif;?>
-        </p>
-        <div class="review content"><?php echo nl2br($this->escapeHtml($this->getReviewData()->getDetail())) ?></div>
+        <div class="review-title"><?php echo $this->escapeHtml($this->getReviewData()->getTitle()) ?></div>
+        <div class="review-content"><?php echo nl2br($this->escapeHtml($this->getReviewData()->getDetail())) ?></div>
+        <div class="review-date">
+            <?php echo __('Submitted on %1', '<time class="date">' . $this->dateFormat($this->getReviewData()->getCreatedAt()) . '</time>') ?>
+        </div>
     </div>
 </div>
 <div class="actions-toolbar">
diff --git a/app/code/Magento/Review/view/frontend/templates/form.phtml b/app/code/Magento/Review/view/frontend/templates/form.phtml
index 5a9b51ecd1dd141b58753f626ec2c2838ba2c23c..0eb61fb9b498812412b4dbcf51a98d34b67a381e 100644
--- a/app/code/Magento/Review/view/frontend/templates/form.phtml
+++ b/app/code/Magento/Review/view/frontend/templates/form.phtml
@@ -22,38 +22,38 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 ?>
-<div class="block add review">
-    <div class="title"><strong><?php echo __('Write Your Own Review') ?></strong></div>
-<div class="content">
+<div class="block review-add">
+    <div class="block-title"><strong><?php echo __('Write Your Own Review') ?></strong></div>
+<div class="block-content">
 <?php if ($this->getAllowWriteReviewFlag()): ?>
-<form action="<?php echo $this->getAction() ?>" method="post" id="review-form">
+<form action="<?php echo $this->getAction() ?>" class="review-form" method="post" id="review-form">
     <?php echo $this->getBlockHtml('formkey'); ?>
     <?php echo $this->getChildHtml('form_fields_before')?>
-    <fieldset class="fieldset" data-hasrequired="<?php __('* Required Fields'); ?>">
-        <legend class="legend"><span><?php echo __("You're reviewing:"); ?></span><strong><?php echo $this->escapeHtml($this->getProductInfo()->getName()) ?></strong></legend><br />
+    <fieldset class="fieldset review-fieldset" data-hasrequired="<?php __('* Required Fields'); ?>">
+        <legend class="legend review-legend"><span><?php echo __("You're reviewing:"); ?></span><strong><?php echo $this->escapeHtml($this->getProductInfo()->getName()) ?></strong></legend><br />
         <?php if ($this->getRatings() && $this->getRatings()->getSize()): ?>
         <span id="input-message-box"></span>
-        <fieldset class="field ratings vote required">
-            <legend class="label"><span><?php echo __('How do you rate this product?') ?><span></legend>
+        <fieldset class="field required review-field-ratings">
+            <legend class="label"><span><?php echo __('How do you rate this product?') ?><span></legend><br/>
             <div class="control">
                 <div class="nested" id="product-review-table">
                     <?php foreach ($this->getRatings() as $_rating): ?>
-                        <div class="field choice rating">
-                            <label class="label" id="<?php echo $this->escapeHtml($_rating->getRatingCode()) ?>_rating_label"><span><?php echo $this->escapeHtml($_rating->getRatingCode()) ?>:</span></label>
-                            <div class="control rating vote">
+                        <div class="field choice review-field-rating">
+                            <label class="label" id="<?php echo $this->escapeHtml($_rating->getRatingCode()) ?>_rating_label"><span><?php echo $this->escapeHtml($_rating->getRatingCode()) ?></span></label>
+                            <div class="control review-control-vote">
                             <?php $options = $_rating->getOptions();?>
                             <?php $iterator = 1; foreach ($options as $_option): ?>
-                                <input 
-                                    type="radio" 
-                                    name="ratings[<?php echo $_rating->getId() ?>]" 
-                                    id="<?php echo $this->escapeHtml($_rating->getRatingCode()) ?>_<?php echo $_option->getValue() ?>" 
-                                    value="<?php echo $_option->getId() ?>" 
-                                    class="radio" 
+                                <input
+                                    type="radio"
+                                    name="ratings[<?php echo $_rating->getId() ?>]"
+                                    id="<?php echo $this->escapeHtml($_rating->getRatingCode()) ?>_<?php echo $_option->getValue() ?>"
+                                    value="<?php echo $_option->getId() ?>"
+                                    class="radio"
                                     data-validate="{required:true, messages:{required:'Please select one of each of the ratings above.'}}"
                                     aria-labelledby="<?php echo $this->escapeHtml($_rating->getRatingCode()) ?>_rating_label <?php echo $this->escapeHtml($_rating->getRatingCode()) ?>_<?php echo $_option->getValue() ?>_label" />
-                                <label 
-                                    class="rating-<?php echo $iterator; ?>" 
-                                    for="<?php echo $this->escapeHtml($_rating->getRatingCode()) ?>_<?php echo $_option->getValue() ?>" 
+                                <label
+                                    class="rating-<?php echo $iterator; ?>"
+                                    for="<?php echo $this->escapeHtml($_rating->getRatingCode()) ?>_<?php echo $_option->getValue() ?>"
                                     title="<?php echo __('%1 %2', $iterator, $iterator > 1 ? 'stars' : 'star') ?>"
                                     id="<?php echo $this->escapeHtml($_rating->getRatingCode()) ?>_<?php echo $_option->getValue() ?>_label">
                                     <span><?php echo __('%1 %2', $iterator, $iterator > 1 ? 'stars' : 'star') ?></span>
@@ -68,27 +68,27 @@
             </div>
         </fieldset>
     <?php endif ?>
-        <div class="field nickname required">
+        <div class="field review-field-nickname required">
             <label for="nickname_field" class="label"><span><?php echo __('Nickname') ?></span></label>
             <div class="control">
                 <input type="text" name="nickname" id="nickname_field" class="input-text" data-validate="{required:true}" value="<?php echo $this->escapeHtml($data->getNickname()) ?>" />
             </div>
         </div>
-        <div class="field summary required">
+        <div class="field review-field-summary required">
             <label for="summary_field" class="label"><span><?php echo __('Summary of Your Review') ?></span></label>
             <div class="control">
                 <input type="text" name="title" id="summary_field" class="input-text" data-validate="{required:true}" value="<?php echo $this->escapeHtml($data->getTitle()) ?>" />
             </div>
         </div>
-        <div class="field text required">
+        <div class="field review-field-text required">
             <label for="review_field" class="label"><span><?php echo __('Review') ?></span></label>
             <div class="control">
                 <textarea name="detail" id="review_field" cols="5" rows="3" data-validate="{required:true}"><?php echo $this->escapeHtml($data->getDetail()) ?></textarea>
             </div>
         </div>
     </fieldset>
-    <div class="actions-toolbar">
-        <div class="primary">
+    <div class="actions-toolbar review-form-actions">
+        <div class="primary actions-primary">
             <button type="submit" class="action submit primary"><span><?php echo __('Submit Review') ?></span></button>
         </div>
         <!-- <button type="button" class="action cancel"><span><?php echo __('Cancel') ?></span></button> -->
@@ -109,9 +109,11 @@
     })(jQuery);
 </script>
 <?php else: ?>
-    <p class="review notlogged" id="review-form">
-        <?php echo __('Only registered users can write reviews. Please, <a href="%1">log in</a> or <a href="%2">register</a>', $this->getLoginLink(), $this->helper('Magento\Customer\Helper\Data')->getRegisterUrl()) ?>
-    </p>
+    <div class="message info notlogged" id="review-form">
+        <div>
+            <?php echo __('Only registered users can write reviews. Please, <a href="%1">log in</a> or <a href="%2">register</a>', $this->getLoginLink(), $this->helper('Magento\Customer\Helper\Data')->getRegisterUrl()) ?>
+        </div>
+    </div>
 <?php endif ?>
 </div>
 </div>
diff --git a/app/code/Magento/Review/view/frontend/templates/helper/summary.phtml b/app/code/Magento/Review/view/frontend/templates/helper/summary.phtml
index 5cdc0be511e64fbc68d17530611eede55f7040d5..11b60ed74379c17fdce1f5a75657af7f43c8b5ef 100644
--- a/app/code/Magento/Review/view/frontend/templates/helper/summary.phtml
+++ b/app/code/Magento/Review/view/frontend/templates/helper/summary.phtml
@@ -22,44 +22,30 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 ?>
-<?php $url = $this->getReviewsUrl(); ?>
+<?php $url = $this->getReviewsUrl() . '#reviews'; ?>
 <?php $urlForm = $this->getReviewsUrl() . '#review-form'; ?>
-<?php //$url = $this->getProduct()->getProductUrl() . '#info-product_reviews' ?>
-<?php //$urlForm = $this->getProduct()->getProductUrl() . '#info-product_reviews' ?>
 <?php if ($this->getReviewsCount()): ?>
 <?php $rating = $this->getRatingSummary(); ?>
-<div class="product reviews summary<?php echo !$rating ? ' no-rating' :''?>">
+<div class="product-reviews-summary<?php echo !$rating ? ' no-rating' :''?>">
     <?php if ($rating):?>
-    <div class="rating summary">
+    <div class="rating-summary">
          <span class="label"><span><?php echo __('Rating') ?>:</span></span>
-         <div class="rating result" title="<?php echo $rating; ?>%">
+         <div class="rating-result" title="<?php echo $rating; ?>%">
              <span style="width:<?php echo $rating; ?>%"><span><?php echo $rating; ?>%</span></span>
          </div>
      </div>
     <?php endif;?>
-    <div class="reviews actions">
+    <div class="reviews-actions">
         <a class="action view" href="<?php echo $url ?>"><?php echo $this->getReviewsCount() ?>&nbsp;<span><?php echo ($this->getReviewsCount() == 1) ? __('Review') : __('Reviews') ?></span></a>
         <a class="action add" href="<?php echo $urlForm ?>"><?php echo __('Add Your Review') ?></a>
     </div>
 </div>
 <?php elseif ($this->getDisplayIfEmpty()): ?>
-<div class="product reviews summary empty">
-    <a class="action add" href="<?php echo $urlForm; ?>">
-        <?php echo __('Be the first to review this product') ?>
-    </a>
+<div class="product-reviews-summary empty">
+    <div class="reviews-actions">
+        <a class="action add" href="<?php echo $urlForm; ?>">
+            <?php echo __('Be the first to review this product') ?>
+        </a>
+    </div>
 </div>
 <?php endif; ?>
-<script type="text/javascript">
-    (function($) {
-        $(document).ready(function() {
-            $('.reviews.summary .action').click(function(evt){
-                if($('#product_reviews').length > 0) {
-                    evt.preventDefault();
-                    $('[data-sections]').terms({start:'product_reviews'});
-                } else {
-                    return
-                }
-            })
-        });
-    })(jQuery);
-</script>
\ No newline at end of file
diff --git a/app/code/Magento/Review/view/frontend/templates/helper/summary_short.phtml b/app/code/Magento/Review/view/frontend/templates/helper/summary_short.phtml
index 804494a3bae3fe34e5f5b1ff1b4b406103ddd70c..edb4ff0f052d70e3f229cf42dbd8ce3899d7e78e 100644
--- a/app/code/Magento/Review/view/frontend/templates/helper/summary_short.phtml
+++ b/app/code/Magento/Review/view/frontend/templates/helper/summary_short.phtml
@@ -22,45 +22,29 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 ?>
-<?php $url = $this->getReviewsUrl(); ?>
+<?php $url = $this->getReviewsUrl() . '#reviews'; ?>
 <?php $urlForm = $this->getReviewsUrl() . '#review-form'; ?>
-<?php //$url = $this->getProduct()->getProductUrl() . '#info-product_reviews' ?>
-<?php //$urlForm = $this->getProduct()->getProductUrl() . '#info-product_reviews' ?>
 <?php if ($this->getReviewsCount()): ?>
 <?php $rating = $this->getRatingSummary(); ?>
-<div class="product reviews summary short<?php echo !$rating ? ' no-rating' :''?>">
+<div class="product-reviews-summary short<?php echo !$rating ? ' no-rating' :''?>">
     <?php if ($rating):?>
-    <div class="rating summary">
+    <div class="rating-summary">
         <span class="label"><span><?php echo __('Rating') ?>:</span></span>
-        <div class="rating result" title="<?php echo $rating; ?>%">
-            <span style="width:<?php echo $rating; ?>%">
-                <span><?php echo $rating; ?>%</span>
-            </span>
+        <div class="rating-result" title="<?php echo $rating; ?>%">
+            <span style="width:<?php echo $rating; ?>%"><span><?php echo $rating; ?>%</span></span>
         </div>
     </div>
     <?php endif;?>
-    <div class="reviews actions">
-        <a class="action view" href="<?php echo $urlForm ?>"><?php echo $this->getReviewsCount() ?>&nbsp;<span><?php echo ($this->getReviewsCount() == 1) ? __('Review') : __('Reviews') ?></span></a>
+    <div class="reviews-actions">
+        <a class="action view" href="<?php echo $url ?>"><?php echo $this->getReviewsCount() ?>&nbsp;<span><?php echo ($this->getReviewsCount() == 1) ? __('Review') : __('Reviews') ?></span></a>
     </div>
 </div>
 <?php elseif ($this->getDisplayIfEmpty()): ?>
-<div class="product reviews summary short empty">
-    <a class="action add" href="<?php echo $urlForm; ?>">
-        <?php echo __('Be the first to review this product') ?>
-    </a>
+<div class="product-reviews-summary short empty">
+    <div class="reviews-actions">
+        <a class="action add" href="<?php echo $urlForm; ?>">
+            <?php echo __('Be the first to review this product') ?>
+        </a>
+    </div>
 </div>
 <?php endif; ?>
-<script type="text/javascript">
-    (function($) {
-        $(document).ready(function() {
-            $('.reviews.summary .action').click(function(evt){
-                if($('#product_reviews').length > 0) {
-                    evt.preventDefault();
-                    $('[data-sections]').terms({start:'product_reviews'});
-                } else {
-                    return
-                }
-            })
-        });
-    })(jQuery);
-</script>
diff --git a/app/code/Magento/Review/view/frontend/templates/product/view/list.phtml b/app/code/Magento/Review/view/frontend/templates/product/view/list.phtml
index 9104cd535b17f76c9eef44ab18a1f94899487ba0..8ab88ed9e1f26b9b9dd167a3ecd7b03863848d5a 100644
--- a/app/code/Magento/Review/view/frontend/templates/product/view/list.phtml
+++ b/app/code/Magento/Review/view/frontend/templates/product/view/list.phtml
@@ -22,51 +22,60 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 ?>
-
-<?php 
+<?php
+/**
+ * @description:
+ *
+ */
+?>
+<?php
     $_items = $this->getReviewsCollection()->getItems();
     $format = $this->getDateFormat() ?: 'short';
 ?>
 <?php if (count($_items)):?>
-<div class="block reviews list" id="customer-reviews">
-    <div class="title">
+<div class="block review-list" id="customer-reviews">
+    <div class="block-title">
         <strong><?php echo __('Customer Reviews') ?></strong>
     </div>
-    <div class="content">
-        <div class="toolbar products">
+    <div class="block-content">
+        <div class="toolbar review-toolbar">
             <?php echo $this->getChildHtml('toolbar') ?>
         </div>
-    <ol class="reviews items">
-    <?php foreach ($_items as $_review):?>
-        <li class="item review">
-            <?php foreach ($_review->getRatingVotes() as $_vote): ?>
-            <div class="rating summary item">
-                <span class="label"><span><?php echo $this->escapeHtml($_vote->getRatingCode()) ?>:</span></span>
-                <div class="rating result" title="<?php echo $_vote->getPercent() ?>%">
-                    <span style="width:<?php echo $_vote->getPercent() ?>%">
-                        <span><?php echo $_vote->getPercent() ?>%</span>
-                    </span>
+        <ol class="items review-items">
+        <?php foreach ($_items as $_review):?>
+            <li class="item review-item">
+                <div class="review-title"><?php echo $this->escapeHtml($_review->getTitle()) ?></div>
+                <?php if (count($_review->getRatingVotes())): ?>
+                    <div class="review-ratings">
+                    <?php foreach ($_review->getRatingVotes() as $_vote): ?>
+                    <div class="rating-summary item">
+                        <span class="label rating-label"><span><?php echo $this->escapeHtml($_vote->getRatingCode()) ?></span></span>
+                        <div class="rating-result" title="<?php echo $_vote->getPercent() ?>%">
+                            <span style="width:<?php echo $_vote->getPercent() ?>%">
+                                <span><?php echo $_vote->getPercent() ?>%</span>
+                            </span>
+                        </div>
+                    </div>
+                    <?php endforeach; ?>
+                    </div>
+                <?php endif; ?>
+                <div class="review-content">
+                    <?php echo nl2br($this->escapeHtml($_review->getDetail())) ?>
+                </div>
+                <div class="review-details">
+                    <p class="review-author">
+                        <span class="review-details-label"><?php echo __('Review by')?></span>
+                        <strong class="review-details-value"><?php echo $this->escapeHtml($_review->getNickname()) ?></strong>
+                    </p>
+                    <p class="review-date">
+                        <span class="review-details-label"><?php echo __('Posted on') ?></span>
+                        <time class="review-details-value"><?php echo $this->formatDate($_review->getCreatedAt(), $format) ?></time>
+                    </p>
                 </div>
-            </div>
-            <?php endforeach; ?>
-            <div class="review details">
-                <p class="author">
-                    <span><?php echo __('Review by')?></span>
-                    <strong class="nickname"><?php echo $this->escapeHtml($_review->getNickname()) ?></strong>
-                </p>
-                <p class="review date">
-                    <span><?php echo __('Posted on') ?></span>
-                    <time class="date"><?php echo $this->formatDate($_review->getCreatedAt(), $format) ?></time>
-                </p>
-            </div>
-            <div class="review title"><?php echo $this->escapeHtml($_review->getTitle()) ?></div>
-            <div class="review content">
-                <?php echo nl2br($this->escapeHtml($_review->getDetail())) ?>
-            </div>
-        </li>
-    <?php endforeach; ?>
-    </ol>
-        <div class="toolbar products">
+            </li>
+        <?php endforeach; ?>
+        </ol>
+        <div class="toolbar review-toolbar">
             <?php echo $this->getChildHtml('toolbar') ?>
         </div>
     </div>
diff --git a/app/code/Magento/Review/view/frontend/templates/review.phtml b/app/code/Magento/Review/view/frontend/templates/review.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..eb2ff606ce27a4f465824ff050c4bdf1dbda8dd4
--- /dev/null
+++ b/app/code/Magento/Review/view/frontend/templates/review.phtml
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+?>
+
+<div id="product-review-container"></div>
+<?php echo $this->getChildHtml(); ?>
+
+<script type="text/javascript">
+//<![CDATA[
+function processReviews(url,fromPages) {
+(function($) {
+    $.ajax({
+        url: url,
+        dataType: 'html'
+    }).done(function(data) {
+        $('#product-review-container').html(data);
+        $('.pages a').each(function(index, element) {
+            $(element).click(function(event) {
+                processReviews($(element).attr('href'), true);
+                event.preventDefault();
+            });
+        });
+    }).complete(function(){
+        if (fromPages == true) {
+            $('html, body').animate({
+                scrollTop: $('#reviews').offset().top - 50
+            }, 300);
+        }
+    });
+})(jQuery);
+}
+processReviews('<?php echo $this->getProductReviewUrl();?>');
+
+jQuery(function() {
+    jQuery('.product-info-main .reviews-actions a').click(function(event) {
+        event.preventDefault();
+        var acnchor = jQuery(this).attr('href').replace(/^.*?(#|$)/,'');
+        jQuery(".product.data.items [data-role='content']").each(function(index){
+            if(this.id == "reviews") {
+                jQuery(".product.data.items").tabs('activate',index);
+                jQuery('html, body').animate({
+                    scrollTop: jQuery('#' + acnchor).offset().top - 50
+                }, 300);
+            }
+        })
+    })
+});
+
+//]]>
+</script>
diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php
index c9b48275f79028df25c4b752dc90db9d8271d6bc..b5c0720cae93d2b37296e3529ee77dc877c60269 100644
--- a/app/code/Magento/Sales/Model/Order.php
+++ b/app/code/Magento/Sales/Model/Order.php
@@ -1521,6 +1521,7 @@ class Order extends \Magento\Sales\Model\AbstractModel
         if (!$this->_salesData->canSendNewOrderEmail($storeId)) {
             return $this;
         }
+
         // Get the destination email addresses to send copies to
         $copyTo = $this->_getEmails(self::XML_PATH_EMAIL_COPY_TO);
         $copyMethod = $this->_scopeConfig->getValue(
diff --git a/app/code/Magento/Sales/Model/Order/Payment.php b/app/code/Magento/Sales/Model/Order/Payment.php
index e34716cca608d585183ebb1ae4bea4e09ae652d7..8e0cf75fd9c4978dc8088866d1debaf6de81844e 100644
--- a/app/code/Magento/Sales/Model/Order/Payment.php
+++ b/app/code/Magento/Sales/Model/Order/Payment.php
@@ -355,6 +355,8 @@ class Payment extends \Magento\Payment\Model\Info
             } else {
                 $orderState = \Magento\Sales\Model\Order::STATE_PROCESSING;
                 $this->processAction($action, $order);
+                $orderState = $order->getState() ? $order->getState() : $orderState;
+                $orderStatus = $order->getStatus() ? $order->getStatus() : $orderStatus;
             }
         }
 
@@ -537,9 +539,10 @@ class Payment extends \Magento\Payment\Model\Info
      * TODO: eliminate logic duplication with capture()
      *
      * @param float $amount
+     * @param bool $skipFraudDetection
      * @return $this
      */
-    public function registerCaptureNotification($amount)
+    public function registerCaptureNotification($amount, $skipFraudDetection = false)
     {
         $this->_generateTransactionId(
             \Magento\Sales\Model\Order\Payment\Transaction::TYPE_CAPTURE,
@@ -557,7 +560,7 @@ class Payment extends \Magento\Payment\Model\Info
                 $order->addRelatedObject($invoice);
                 $this->setCreatedInvoice($invoice);
             } else {
-                $this->setIsFraudDetected(true);
+                $this->setIsFraudDetected(!$skipFraudDetection);
                 $this->_updateTotals(array('base_amount_paid_online' => $amount));
             }
         }
@@ -857,10 +860,10 @@ class Payment extends \Magento\Payment\Model\Info
             $amount = $amountRefundLeft;
         }
 
-        if ($amount <= 0) {
+        if ($amount != $baseGrandTotal) {
             $order->addStatusHistoryComment(
                 __(
-                    'IPN "Refunded". Refund issued by merchant. Registered notification about refunded amount of %1. Transaction ID: "%2"',
+                    'IPN "Refunded". Refund issued by merchant. Registered notification about refunded amount of %1. Transaction ID: "%2". Credit Memo has not been created. Please create offline Credit Memo.',
                     $this->_formatPrice($notificationAmount),
                     $this->getTransactionId()
                 ),
@@ -1067,7 +1070,6 @@ class Payment extends \Magento\Payment\Model\Info
                         $this,
                         $transactionId
                     );
-                } else {
                 }
                 if ($this->getIsTransactionApproved()) {
                     $result = true;
@@ -1089,9 +1091,16 @@ class Payment extends \Magento\Payment\Model\Info
         }
 
         // process payment in case of positive or negative result, or add a comment
-        if (-1 === $result) {
-            // switch won't work with such $result!
-            $order->addStatusHistoryComment($message);
+        if (-1 === $result) { // switch won't work with such $result!
+            if ($order->getState() != \Magento\Sales\Model\Order::STATE_PAYMENT_REVIEW) {
+                $status = $this->getIsFraudDetected() ? \Magento\Sales\Model\Order::STATUS_FRAUD : false;
+                $order->setState(\Magento\Sales\Model\Order::STATE_PAYMENT_REVIEW, $status, $message);
+                if ($transactionId) {
+                    $this->setLastTransId($transactionId);
+                }
+            } else {
+                $order->addStatusHistoryComment($message);
+            }
         } elseif (true === $result) {
             if ($invoice) {
                 $invoice->pay();
@@ -1167,6 +1176,13 @@ class Payment extends \Magento\Payment\Model\Info
      */
     protected function _authorize($isOnline, $amount)
     {
+        // check for authorization amount to be equal to grand total
+        $this->setShouldCloseParentTransaction(false);
+        $isSameCurrency = $this->_isSameCurrency();
+        if (!$isSameCurrency || !$this->_isCaptureFinal($amount)) {
+            $this->setIsFraudDetected(true);
+        }
+
         // update totals
         $amount = $this->_formatAmount($amount, true);
         $this->setBaseAmountAuthorized($amount);
@@ -1187,11 +1203,19 @@ class Payment extends \Magento\Payment\Model\Info
                 $this->_formatPrice($amount)
             );
             $state = \Magento\Sales\Model\Order::STATE_PAYMENT_REVIEW;
+        } else {
             if ($this->getIsFraudDetected()) {
-                $status = \Magento\Sales\Model\Order::STATUS_FRAUD;
+                $message = __(
+                    'Order is suspended as its authorizing amount %1 is suspected to be fraudulent.',
+                    $this->_formatPrice($amount, $this->getCurrencyCode())
+                );
+            } else {
+                $message = __('Authorized amount of %1', $this->_formatPrice($amount));
             }
-        } else {
-            $message = __('Authorized amount of %1', $this->_formatPrice($amount));
+        }
+        if ($this->getIsFraudDetected()) {
+            $state = \Magento\Sales\Model\Order::STATE_PAYMENT_REVIEW;
+            $status = \Magento\Sales\Model\Order::STATUS_FRAUD;
         }
 
         // update transactions, order state and add comments
diff --git a/app/code/Magento/Sales/Model/Resource/Report/Bestsellers/Collection.php b/app/code/Magento/Sales/Model/Resource/Report/Bestsellers/Collection.php
index d079180c09e35f43050b17a0061847334e2f4faa..abae4d21b0e8933dd442c494ae681f7f420611cb 100644
--- a/app/code/Magento/Sales/Model/Resource/Report/Bestsellers/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Report/Bestsellers/Collection.php
@@ -133,7 +133,7 @@ class Collection extends \Magento\Sales\Model\Resource\Report\Collection\Abstrac
      *
      * @return $this
      */
-    protected function _initSelect()
+    protected function _applyAggregatedTable()
     {
         $select = $this->getSelect();
 
diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_creditmemo.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_creditmemo.xml
index 99b5cebd27edf8abfcdc411a537264c70394501c..bcb05b783805c2bdbcd633844f9b2147320d4af4 100644
--- a/app/code/Magento/Sales/view/frontend/layout/sales_order_creditmemo.xml
+++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_creditmemo.xml
@@ -26,11 +26,16 @@
 <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Core/etc/layout_single.xsd">
     <update handle="sales_order_creditmemo_renderers" />
     <update handle="customer_account"/>
-    <referenceContainer name="content">
-        <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info">
+    <referenceContainer name="page.main.title">
+        <block class="Magento\Sales\Block\Order\Info" name="order.status" template="order/order_status.phtml" />
+        <block class="Magento\Sales\Block\Order\Info" name="order.date" template="order/order_date.phtml" />
+        <container name="order.actions.container" htmlTag="div" htmlClass="actions-toolbar order-actions-toolbar">
             <block class="Magento\Sales\Block\Order\Info\Buttons" as="buttons" name="sales.order.info.buttons" cacheable="false"/>
-        </block>
-        <block class="Magento\Sales\Block\Order\Creditmemo" name="sales.order.creditmemo" after="sales.order.info" cacheable="false">
+            <block class="Magento\Sales\Block\Order\Info" name="order.rss" template="order/order_rss.phtml" />
+        </container>
+    </referenceContainer>
+    <referenceContainer name="content">
+        <block class="Magento\Sales\Block\Order\Creditmemo" name="sales.order.creditmemo" cacheable="false">
             <block class="Magento\Sales\Block\Order\Creditmemo\Items" name="creditmemo_items" template="order/creditmemo/items.phtml">
                 <block class="Magento\Framework\View\Element\RendererList" name="sales.order.creditmemo.renderers" as="renderer.list" />
                 <block class="Magento\Sales\Block\Order\Creditmemo\Totals" name="creditmemo_totals" template="order/totals.phtml">
diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_info_links.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_info_links.xml
index fba533f2bd6e35b9525a58a3a940e2fade593556..aabd36d18af947e31b837fbb2aedef32976af5a4 100644
--- a/app/code/Magento/Sales/view/frontend/layout/sales_order_info_links.xml
+++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_info_links.xml
@@ -24,15 +24,15 @@
  */
 -->
 <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Core/etc/layout_single.xsd">
-    <referenceBlock name="sales.order.info">
-        <block class="Magento\Framework\View\Element\Html\Links" as="links" name="sales.order.info.links">
+    <referenceContainer name="content">
+        <block class="Magento\Framework\View\Element\Html\Links" as="links" name="sales.order.info.links" before="-">
             <arguments>
-                <argument name="css_class" xsi:type="string">items</argument>
+                <argument name="css_class" xsi:type="string">items order-links</argument>
             </arguments>
             <block class="Magento\Sales\Block\Order\Link" name="sales.order.info.links.information">
                 <arguments>
                     <argument name="path" xsi:type="string">sales/order/view</argument>
-                    <argument name="label" xsi:type="string">Order Information</argument>
+                    <argument name="label" xsi:type="string">Items Ordered</argument>
                 </arguments>
             </block>
             <block class="Magento\Sales\Block\Order\Link" name="sales.order.info.links.invoice">
@@ -57,5 +57,5 @@
                 </arguments>
             </block>
         </block>
-    </referenceBlock>
+    </referenceContainer>
 </layout>
diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_invoice.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_invoice.xml
index 999471a570737e6ce316e4dc3629d35e899d1a06..13934744f2c830b3a377867449e8003236f33559 100644
--- a/app/code/Magento/Sales/view/frontend/layout/sales_order_invoice.xml
+++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_invoice.xml
@@ -26,11 +26,16 @@
 <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Core/etc/layout_single.xsd">
     <update handle="customer_account"/>
     <update handle="sales_order_invoice_renderers" />
-    <referenceContainer name="content">
-        <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info">
+    <referenceContainer name="page.main.title">
+        <block class="Magento\Sales\Block\Order\Info" name="order.status" template="order/order_status.phtml" />
+        <block class="Magento\Sales\Block\Order\Info" name="order.date" template="order/order_date.phtml" />
+        <container name="order.actions.container" htmlTag="div" htmlClass="actions-toolbar order-actions-toolbar">
             <block class="Magento\Sales\Block\Order\Info\Buttons" as="buttons" name="sales.order.info.buttons" cacheable="false"/>
-        </block>
-        <block class="Magento\Sales\Block\Order\Invoice" name="sales.order.invoice" after="sales.order.info" cacheable="false">
+            <block class="Magento\Sales\Block\Order\Info" name="order.rss" template="order/order_rss.phtml" />
+        </container>
+    </referenceContainer>
+    <referenceContainer name="content">
+        <block class="Magento\Sales\Block\Order\Invoice" name="sales.order.invoice" cacheable="false">
             <block class="Magento\Sales\Block\Order\Invoice\Items" name="invoice_items" template="order/invoice/items.phtml">
                 <block class="Magento\Framework\View\Element\RendererList" name="sales.order.invoice.renderers" as="renderer.list"/>
                 <block class="Magento\Sales\Block\Order\Invoice\Totals" name="invoice_totals" template="order/totals.phtml">
@@ -43,6 +48,7 @@
                 <block class="Magento\Sales\Block\Order\Comments" name="invoice_comments" template="order/comments.phtml"/>
             </block>
         </block>
+        <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info" after="-" />
     </referenceContainer>
     <update handle="sales_order_info_links"/>
     <block class="Magento\Framework\View\Element\Template" name="additional.product.info" template="Magento_Core::template.phtml"/>
diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_shipment.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_shipment.xml
index 606039127986620b849a29feaccf01b83ede25fd..45a152d0dd0cdb87a423fa7c3a103c72753d2eb3 100644
--- a/app/code/Magento/Sales/view/frontend/layout/sales_order_shipment.xml
+++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_shipment.xml
@@ -25,10 +25,16 @@
 -->
 <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Core/etc/layout_single.xsd">
     <update handle="customer_account"/>
-    <referenceContainer name="content">
-        <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info">
+    <referenceContainer name="page.main.title">
+        <block class="Magento\Sales\Block\Order\Info" name="order.status" template="order/order_status.phtml" />
+        <block class="Magento\Sales\Block\Order\Info" name="order.date" template="order/order_date.phtml" />
+        <container name="order.actions.container" htmlTag="div" htmlClass="actions-toolbar order-actions-toolbar">
             <block class="Magento\Sales\Block\Order\Info\Buttons" as="buttons" name="sales.order.info.buttons" cacheable="false"/>
-        </block>
+            <block class="Magento\Sales\Block\Order\Info" name="order.rss" template="order/order_rss.phtml" />
+        </container>
+    </referenceContainer>
+    <referenceContainer name="content">
+        <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info" after="sales.order.shipment" />
     </referenceContainer>
     <update handle="sales_order_info_links"/>
     <block class="Magento\Framework\View\Element\Template" name="additional.product.info" template="Magento_Core::template.phtml"/>
diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_view.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_view.xml
index 44686104961afe15082d70c6276f4e912287c8d1..bd4dce6776bb173a31b0105249b377fbde85e29b 100644
--- a/app/code/Magento/Sales/view/frontend/layout/sales_order_view.xml
+++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_view.xml
@@ -26,11 +26,17 @@
 <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Core/etc/layout_single.xsd">
     <update handle="customer_account"/>
     <update handle="sales_order_item_renderers"/>
-    <referenceContainer name="content">
-        <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info">
+    <referenceContainer name="page.main.title">
+        <block class="Magento\Sales\Block\Order\Info" name="order.status" template="order/order_status.phtml" />
+        <block class="Magento\Sales\Block\Order\Info" name="order.date" template="order/order_date.phtml" />
+        <container name="order.actions.container" htmlTag="div" htmlClass="actions-toolbar order-actions-toolbar">
             <block class="Magento\Sales\Block\Order\Info\Buttons" as="buttons" name="sales.order.info.buttons" cacheable="false"/>
-        </block>
-        <block class="Magento\Sales\Block\Order\View" name="sales.order.view" after="sales.order.info" cacheable="false">
+            <block class="Magento\Sales\Block\Order\Info" name="order.rss" template="order/order_rss.phtml" />
+        </container>
+    </referenceContainer>
+    <referenceContainer name="content">
+        <block class="Magento\Sales\Block\Order\View" name="order.comments" template="order/order_comments.phtml" before="sales.order.info.links" />
+        <block class="Magento\Sales\Block\Order\View" name="sales.order.view" cacheable="false">
             <block class="Magento\Sales\Block\Order\Items" name="order_items" template="order/items.phtml">
                 <block class="Magento\Framework\View\Element\RendererList" name="sales.order.items.renderers" as="renderer.list" />
                 <block class="Magento\Sales\Block\Order\Totals" name="order_totals" template="order/totals.phtml">
@@ -42,6 +48,7 @@
                 </block>
             </block>
         </block>
+        <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info" after="sales.order.view" />
     </referenceContainer>
     <update handle="sales_order_info_links"/>
     <block class="Magento\Framework\View\Element\Template" name="additional.product.info" template="Magento_Core::template.phtml"/>
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/creditmemo.phtml b/app/code/Magento/Sales/view/frontend/templates/order/creditmemo.phtml
index ded58aa14fe8991b5f814b6d6dd69aa68d17812f..ea441b5f441f05e42c2e223a5772b373465ab0bd 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/creditmemo.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/creditmemo.phtml
@@ -22,7 +22,7 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 ?>
-<div class="order details items creditmemo">
+<div class="order-details-items creditmemo">
     <?php echo $this->getChildHtml('creditmemo_items') ?>
     <div class="actions-toolbar">
         <div class="secondary">
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/creditmemo/items.phtml b/app/code/Magento/Sales/view/frontend/templates/order/creditmemo/items.phtml
index 31c8f81b66bceece4f256a5c4d7a2c21f30c3ee9..d12df7489333e86cbf30bfd6294e1a2f3f8a7975 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/creditmemo/items.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/creditmemo/items.phtml
@@ -23,17 +23,15 @@
  */
 ?>
 <?php $_order = $this->getOrder() ?>
-<div class="order toolbar">
-    <div class="actions">
-        <a href="<?php echo $this->getPrintAllCreditmemosUrl($_order) ?>"
-           onclick="this.target='_blank'"
-           class="action print">
-            <span><?php echo __('Print All Refunds') ?></span>
-        </a>
-    </div>
+<div class="actions-toolbar">
+    <a href="<?php echo $this->getPrintAllCreditmemosUrl($_order) ?>"
+       onclick="this.target='_blank'"
+       class="action print">
+        <span><?php echo __('Print All Refunds') ?></span>
+    </a>
 </div>
 <?php foreach ($_order->getCreditmemosCollection() as $_creditmemo): ?>
-<div class="order title">
+<div class="order-title">
     <strong><?php echo __('Refund #') ?><?php echo $_creditmemo->getIncrementId(); ?> </strong>
     <a href="<?php echo $this->getPrintCreditmemoUrl($_creditmemo) ?>"
        onclick="this.target='_blank'"
@@ -42,9 +40,8 @@
     </a>
 </div>
 
-<div class="order subtitle caption"><strong><?php echo __('Items Refunded') ?></strong></div>
-<div class="wrapper table order items creditmemo">
-    <table class="data table order items creditmemo" id="my-refund-table-<?php echo $_creditmemo->getId(); ?>">
+<div class="table-wrapper order-items-creditmemo">
+    <table class="data table table-order-items creditmemo" id="my-refund-table-<?php echo $_creditmemo->getId(); ?>">
         <caption class="table caption"><?php echo __('Items Refunded') ?></caption>
         <thead>
             <tr>
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/creditmemo/items/renderer/default.phtml b/app/code/Magento/Sales/view/frontend/templates/order/creditmemo/items/renderer/default.phtml
index 1424311f7e6c4c966b249e9353db9e20a3e2e40e..2728e71d8e523bdd40a606c57ae5913d1429a49b 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/creditmemo/items/renderer/default.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/creditmemo/items/renderer/default.phtml
@@ -25,8 +25,8 @@
 <?php $_item = $this->getItem() ?>
 <?php $_order = $this->getItem()->getOrderItem()->getOrder() ?>
 <tr id="order-item-row-<?php echo $_item->getId() ?>">
-    <td class="col name">
-        <strong class="product name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
+    <td class="col name" data-th="<?php echo $this->escapeHtml(__('Product Name')); ?>">
+        <strong class="product name product-item-name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
         <?php if($_options = $this->getItemOptions()): ?>
         <dl class="item options">
         <?php foreach ($_options as $_option) : ?>
@@ -73,187 +73,94 @@
                data-item-id="<?php echo $_item->getId() ?>"><?php echo __('Gift Message') ?></a>
         <?php endif; ?>
     </td>
-    <td class="col sku"><?php echo $this->prepareSku($this->getSku()) ?></td>
-    <td class="col price">
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-            <span class="price-excl-tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-price">
-                    <?php endif; ?>
-                        <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
-                <?php else: ?>
-                    <span class="cart-price">
-                <?php endif; ?>
-
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
-                    <?php else: ?>
-                        <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
-                    <?php endif; ?>
-                </span>
-
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-
-                    <span class="cart-tax-info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
-                        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
-                            <?php endforeach; ?>
-                            </small>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small></span>
-                            <?php endforeach; ?>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
-                            <?php endforeach; ?>
-                            </small>
-                        <?php endif; ?>
-                    </span>
-
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
-                            <span class="nobr"><?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?></span>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
-            </span>
-            <br />
-        <?php endif; ?>
+    <td class="col sku" data-th="<?php echo $this->escapeHtml(__('SKU')); ?>"><?php echo $this->prepareSku($this->getSku()) ?></td>
+    <td class="col price" data-th="<?php echo $this->escapeHtml(__('Price')); ?>">
         <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-            <span class="price-incl-tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                   <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-price">
-                    <?php endif; ?>
-                        <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
+            <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
                 <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
+                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
                 <?php else: ?>
                     <span class="cart-price">
                 <?php endif; ?>
-
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
-                    <?php else: ?>
-                        <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
-                    <?php endif; ?>
-                </span>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
+                <?php else: ?>
+                    <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
+                <?php endif; ?>
+                    </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-
-                    <span class="cart-tax-info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
-                        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
-                            <?php endforeach; ?>
-                            </small>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small></span>
-                            <?php endforeach; ?>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
-                            <?php endforeach; ?>
-                            </small>
-                        <?php endif; ?>
+                    <span class="cart-tax-info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
+                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                        <?php endforeach; ?>
+                    <?php endif; ?>
                     </span>
 
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                         <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
-                            <span class="nobr"><?php echo __('Total incl. tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?></span>
+                            <span class="weee" data-th="<?php echo __('Total incl. tax'); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?></span>
                         </span>
                     <?php endif; ?>
                 <?php endif; ?>
             </span>
         <?php endif; ?>
-    </td>
-    <td class="col qty"><?php echo $_item->getQty()*1 ?></td>
-    <td class="col subtotal">
+
         <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-            <span class="price-excl-tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-price">
-                    <?php endif; ?>
-                        <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+            <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
                 <?php else: ?>
-                    <span class="cart-price">
-                <?php endif; ?>
+                <span class="cart-price">
+            <?php endif; ?>
 
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
-                    <?php else: ?>
-                        <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
-                    <?php endif; ?>
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
+            <?php else: ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
+            <?php endif; ?>
                 </span>
 
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+                <span class="cart-tax-info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
+                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                        <?php endforeach; ?>
+                    <?php endif; ?>
+                </span>
 
-                    <span class="cart-tax-info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
-                        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
-                            <?php endforeach; ?>
-                            </small>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></small></span>
-                            <?php endforeach; ?>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
-                            <?php endforeach; ?>
-                            </small>
-                        <?php endif; ?>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?></span>
                     </span>
-
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                            <span class="nobr"><?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?></span>
-                        </span>
-                    <?php endif; ?>
                 <?php endif; ?>
+            <?php endif; ?>
             </span>
-            <br />
         <?php endif; ?>
+    </td>
+    <td class="col qty" data-th="<?php echo $this->escapeHtml(__('Qty')); ?>"><?php echo $_item->getQty()*1 ?></td>
+    <td class="col subtotal" data-th="<?php echo $this->escapeHtml(__('Subtotal')); ?>">
         <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-            <span class="price-incl-tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                   <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-price">
-                    <?php endif; ?>
-                        <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
+            <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
                 <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($this->getItem()); ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                     <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
@@ -265,41 +172,77 @@
                     <?php else: ?>
                         <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxRowDisposition()) ?>
                     <?php endif; ?>
-                </span>
+                    </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-
-                    <span class="cart-tax-info" id="subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
+                    <span class="cart-tax-info" id="subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
                         <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
                             <?php endforeach; ?>
-                            </small>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></small></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
-                            </small>
                         <?php endif; ?>
                     </span>
 
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                         <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                            <span class="nobr"><?php echo __('Total incl. tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?></span>
+                            <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?></span>
                         </span>
                     <?php endif; ?>
                 <?php endif; ?>
             </span>
         <?php endif; ?>
+
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
+            <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+            <?php else: ?>
+                <span class="cart-price">
+            <?php endif; ?>
+
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
+            <?php else: ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
+            <?php endif; ?>
+                </span>
+
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+                <span class="cart-tax-info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                    <?php endforeach; ?>
+            <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                    <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                <?php endforeach; ?>
+            <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                    <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                <?php endforeach; ?>
+            <?php endif; ?>
+                </span>
+
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                    <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?></span>
+                </span>
+            <?php endif; ?>
+        <?php endif; ?>
+        </span>
+        <?php endif; ?>
     </td>
-    <td class="col discount"><?php echo $_order->formatPrice(-$_item->getDiscountAmount()) ?></td>
-    <td class="cot total">
+    <td class="col discount" data-th="<?php echo $this->escapeHtml(__('Discount Amount')); ?>"><?php echo $_order->formatPrice(-$_item->getDiscountAmount()) ?></td>
+    <td class="cot total" data-th="<?php echo $this->escapeHtml(__('Row Total')); ?>">
         <?php echo $_order->formatPrice($_item->getRowTotal()-$_item->getDiscountAmount()+$_item->getTaxAmount()+$_item->getWeeeTaxAppliedRowAmount()) ?>
     </td>
 </tr>
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/history.phtml b/app/code/Magento/Sales/view/frontend/templates/order/history.phtml
index 6acad7a99cd668c3401843b6268fd0723705cd54..ef58807040549d84921dc066549c89096f7e4df0 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/history.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/history.phtml
@@ -25,29 +25,31 @@
 <?php $_orders = $this->getOrders(); ?>
 <?php echo $this->getChildHtml('info');?>
 <?php if($_orders->getSize()): ?>
-    <div class="order products toolbar"><?php echo $this->getPagerHtml(); ?></div>
-    <div class="wrapper table orders history">
-        <table class="data table orders history" id="my-orders-table">
+    <?php if ($this->getPagerHtml()): ?>
+        <div class="order-products-toolbar toolbar top"><?php echo $this->getPagerHtml(); ?></div>
+    <?php endif ?>
+    <div class="table-wrapper orders-history">
+        <table class="data table table-order-items history" id="my-orders-table">
             <caption class="table caption"><?php echo __('Orders') ?></caption>
             <thead>
                 <tr>
-                    <th class="col id"><?php echo __('Order #') ?></th>
-                    <th class="col date"><?php echo __('Date') ?></th>
-                    <th class="col shipping"><?php echo __('Ship To') ?></th>
-                    <th class="col total"><?php echo __('Order Total') ?></th>
-                    <th class="col status"><?php echo __('Status') ?></th>
-                    <th class="col actions">&nbsp;</th>
+                    <th scope="col" class="col id"><?php echo __('Order #') ?></th>
+                    <th scope="col" class="col date"><?php echo __('Date') ?></th>
+                    <th scope="col" class="col shipping"><?php echo __('Ship To') ?></th>
+                    <th scope="col" class="col total"><?php echo __('Order Total') ?></th>
+                    <th scope="col" class="col status"><?php echo __('Status') ?></th>
+                    <th scope="col" class="col actions">&nbsp;</th>
                 </tr>
             </thead>
             <tbody>
                 <?php foreach ($_orders as $_order): ?>
                     <tr>
-                        <td class="col id"><?php echo $_order->getRealOrderId() ?></td>
-                        <td class="col date"><?php echo $this->formatDate($_order->getCreatedAtStoreDate()) ?></td>
-                        <td class="col shipping"><?php echo $_order->getShippingAddress() ? $this->escapeHtml($_order->getShippingAddress()->getName()) : '&nbsp;' ?></td>
-                        <td class="col total"><?php echo $_order->formatPrice($_order->getGrandTotal()) ?></td>
-                        <td class="col status"><em><?php echo $_order->getStatusLabel() ?></em></td>
-                        <td class="col actions">
+                        <td data-th="<?php echo $this->escapeHtml(__('Order #')) ?>" class="col id"><?php echo $_order->getRealOrderId() ?></td>
+                        <td data-th="<?php echo $this->escapeHtml(__('Date')) ?>" class="col date"><?php echo $this->formatDate($_order->getCreatedAtStoreDate()) ?></td>
+                        <td data-th="<?php echo $this->escapeHtml(__('Ship To')) ?>" class="col shipping"><?php echo $_order->getShippingAddress() ? $this->escapeHtml($_order->getShippingAddress()->getName()) : '&nbsp;' ?></td>
+                        <td data-th="<?php echo $this->escapeHtml(__('Order Total')) ?>" class="col total"><?php echo $_order->formatPrice($_order->getGrandTotal()) ?></td>
+                        <td data-th="<?php echo $this->escapeHtml(__('Status')) ?>" class="col status"><?php echo $_order->getStatusLabel() ?></td>
+                        <td data-th="" class="col actions">
                             <a href="<?php echo $this->getViewUrl($_order) ?>" class="action view">
                                 <span><?php echo __('View Order') ?></span>
                             </a>
@@ -62,7 +64,9 @@
             </tbody>
         </table>
     </div>
-    <div class="order products toolbar bottom"><?php echo $this->getPagerHtml(); ?></div>
+    <?php if ($this->getPagerHtml()): ?>
+        <div class="order-products-toolbar toolbar bottom"><?php echo $this->getPagerHtml(); ?></div>
+    <?php endif ?>
 <?php else: ?>
     <div class="message info empty"><span><?php echo __('You have placed no orders.'); ?></span></div>
 <?php endif ?>
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/info.phtml b/app/code/Magento/Sales/view/frontend/templates/order/info.phtml
index e21fa9f70938e05b252aaed612d9e1becf176d58..cc5ebaf8ef6f04559c16655822076d2bca7b9a9f 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/info.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/info.phtml
@@ -24,50 +24,48 @@
 ?>
 <?php /** @var $this \Magento\Sales\Block\Order\Info */ ?>
 <?php $_order = $this->getOrder() ?>
-<div class="order details view">
-    <strong class="order status"><?php echo $_order->getStatusLabel() ?></strong>
-    <div class="order toolbar">
-        <?php echo $this->getChildHtml('buttons') ?>
-        <?php echo $this->getStatusHistoryRssUrl($_order) ?>
+<div class="block block-order-details-view">
+    <div class="block-title">
+        <strong><?php echo __('Order Information') ?></strong>
     </div>
-
-    <div class="order info links"><?php echo $this->getChildHtml('links') ?></div>
-
-    <p class="order date"><?php echo __('<span class="label">Order Date:</span> %1', '<date>' . $this->formatDate($_order->getCreatedAtStoreDate(), 'long') . '</date>' ) ?></p>
-<?php if (!$_order->getIsVirtual()): ?>
-    <div class="block order shipping address">
-        <div class="title"><strong><?php echo __('Shipping Address') ?></strong></div>
-        <div class="content">
-            <address><?php echo $_order->getShippingAddress()->format('html') ?></address>
+    <div class="block-content">
+    <?php if (!$_order->getIsVirtual()): ?>
+        <div class="box box-order-shipping-address">
+            <strong class="box-title"><span><?php echo __('Shipping Address') ?></span></strong>
+            <div class="box-content">
+                <address><?php echo $_order->getShippingAddress()->format('html') ?></address>
+            </div>
         </div>
-    </div>
 
-    <div class="block order shipping method">
-        <div class="title"><strong><?php echo __('Shipping Method') ?></strong></div>
-        <div class="content">
-        <?php if ($_order->getShippingDescription()): ?>
-            <?php echo $this->escapeHtml($_order->getShippingDescription()) ?>
-        <?php else: ?>
-            <?php echo __('No shipping information available'); ?>
-        <?php endif; ?>
+        <div class="box box-order-shipping-method">
+            <strong class="box-title">
+                <span><?php echo __('Shipping Method') ?></span>
+            </strong>
+            <div class="box-content">
+            <?php if ($_order->getShippingDescription()): ?>
+                <?php echo $this->escapeHtml($_order->getShippingDescription()) ?>
+            <?php else: ?>
+                <?php echo __('No shipping information available'); ?>
+            <?php endif; ?>
+            </div>
         </div>
-    </div>
+    <?php endif; ?>
 
-<?php endif; ?>
-    <div class="block order billing address">
-        <div class="title">
-            <strong><?php echo __('Billing Address') ?></strong>
-        </div>
-        <div class="content">
-            <address><?php echo $_order->getBillingAddress()->format('html') ?></address>
-        </div>
-    </div>
-    <div class="block order billing method">
-        <div class="title">
-            <strong><?php echo __('Payment Method') ?></strong>
+        <div class="box box-order-billing-address">
+            <strong class="box-title">
+                <span><?php echo __('Billing Address') ?></span>
+            </strong>
+            <div class="box-content">
+                <address><?php echo $_order->getBillingAddress()->format('html') ?></address>
+            </div>
         </div>
-        <div class="content">
-            <?php echo $this->getPaymentInfoHtml() ?>
+        <div class="box box-order-billing-method">
+            <strong class="box-title">
+                <span><?php echo __('Payment Method') ?></span>
+            </strong>
+            <div class="box-content">
+                <?php echo $this->getPaymentInfoHtml() ?>
+            </div>
         </div>
     </div>
 </div>
\ No newline at end of file
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/invoice.phtml b/app/code/Magento/Sales/view/frontend/templates/order/invoice.phtml
index 1d4039efdff3904817b4a3962b80f321d44a60c0..9a0cefcc544256b31784e0709d6451a1324e39e3 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/invoice.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/invoice.phtml
@@ -22,7 +22,7 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 ?>
-<div class="order details items invoice">
+<div class="order-details-items invoice">
     <?php echo $this->getChildHtml('invoice_items') ?>
     <div class="actions-toolbar">
         <div class="secondary">
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/invoice/items.phtml b/app/code/Magento/Sales/view/frontend/templates/order/invoice/items.phtml
index e688936000b92620d01916537b51e9e06b02d73b..fa70c0b03dc433c1353897af149a41f2718ac614 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/invoice/items.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/invoice/items.phtml
@@ -23,17 +23,15 @@
  */
 ?>
 <?php $_order = $this->getOrder() ?>
-<div class="order toolbar">
-    <div class="actions">
-        <a href="<?php echo $this->getPrintAllInvoicesUrl($_order) ?>"
-           target="_blank"
-           class="action print">
-            <span><?php echo __('Print All Invoices') ?></span>
-        </a>
-    </div>
+<div class="actions-toolbar">
+    <a href="<?php echo $this->getPrintAllInvoicesUrl($_order) ?>"
+       target="_blank"
+       class="action print">
+        <span><?php echo __('Print All Invoices') ?></span>
+    </a>
 </div>
 <?php foreach ($_order->getInvoiceCollection() as $_invoice): ?>
-<div class="order title">
+<div class="order-title">
     <strong><?php echo __('Invoice #') ?><?php echo $_invoice->getIncrementId(); ?></strong>
     <a href="<?php echo $this->getPrintInvoiceUrl($_invoice) ?>"
        onclick="this.target='_blank'"
@@ -41,9 +39,8 @@
         <span><?php echo __('Print Invoice') ?></span>
     </a>
 </div>
-<div class="order subtitle caption"><strong><?php echo __('Items Invoiced') ?></strong></div>
-<div class="wrapper table order items invoice">
-    <table class="data table order items invoice" id="my-invoice-table-<?php echo $_invoice->getId(); ?>">
+<div class="table-wrapper table-order-items invoice">
+    <table class="data table table-order-items invoice" id="my-invoice-table-<?php echo $_invoice->getId(); ?>">
         <caption class="table caption"><?php echo __('Items Invoiced') ?></caption>
         <thead>
             <tr>
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/invoice/items/renderer/default.phtml b/app/code/Magento/Sales/view/frontend/templates/order/invoice/items/renderer/default.phtml
index 1f3f3da9bf3b8564b5c97defde0082efa774d3bf..d303068af260e321312b19ae0bf27819b66b04f5 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/invoice/items/renderer/default.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/invoice/items/renderer/default.phtml
@@ -25,8 +25,8 @@
 <?php $_item = $this->getItem() ?>
 <?php $_order = $this->getItem()->getOrderItem()->getOrder() ?>
 <tr id="order-item-row-<?php echo $_item->getId() ?>">
-    <td class="col name">
-        <strong class="product name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
+    <td class="col name" data-th="<?php echo $this->escapeHtml(__('Product Name')); ?>">
+        <strong class="product name product-item-name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
         <?php if($_options = $this->getItemOptions()): ?>
         <dl class="item options">
         <?php foreach ($_options as $_option) : ?>
@@ -64,236 +64,177 @@
             </a>
         <?php endif; ?>
     </td>
-    <td class="col sku"><?php echo $this->prepareSku($this->getSku()) ?></td>
-    <td class="col price">
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-            <span class="price-excl-tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-price">
-                    <?php endif; ?>
-                        <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
+    <td class="col sku" data-th="<?php echo $this->escapeHtml(__('SKU')); ?>"><?php echo $this->prepareSku($this->getSku()) ?></td>
+    <td class="col price" data-th="<?php echo $this->escapeHtml(__('Price')); ?>">
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
+            <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
+                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
+                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
                 <?php else: ?>
                     <span class="cart-price">
                 <?php endif; ?>
 
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
-                    <?php else: ?>
-                        <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
-                    <?php endif; ?>
-
-                </span>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
+                <?php else: ?>
+                    <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
+                <?php endif; ?>
+                    </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-
-                    <span class="cart-tax-info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
+                    <span class="cart-tax-info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
                         <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
                             <?php endforeach; ?>
-                            </small>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
-                            </small>
                         <?php endif; ?>
                     </span>
 
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
-                            <span class="nobr"><?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?></span>
+                        <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
+                            <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?></span>
                         </span>
                     <?php endif; ?>
                 <?php endif; ?>
             </span>
-            <br />
         <?php endif; ?>
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-            <span class="price-incl-tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                   <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-price">
-                    <?php endif; ?>
-                        <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
-                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
-                <?php else: ?>
-                    <span class="cart-price">
-                <?php endif; ?>
 
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?>
-                    <?php else: ?>
-                        <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
-                    <?php endif; ?>
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
+            <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+            <?php else: ?>
+                <span class="cart-price">
+            <?php endif; ?>
 
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
+            <?php else: ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
+            <?php endif; ?>
                 </span>
 
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+                <span class="cart-tax-info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
+                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
+                        <?php endforeach; ?>
+                    <?php endif; ?>
+                </span>
 
-                    <span class="cart-tax-info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
-                        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
-                            <?php endforeach; ?>
-                            </small>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small></span>
-                            <?php endforeach; ?>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
-                            <?php endforeach; ?>
-                            </small>
-                        <?php endif; ?>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?></span>
                     </span>
-
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
-                            <span class="nobr"><?php echo __('Total incl. tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedAmount()); ?></span>
-                        </span>
-                    <?php endif; ?>
                 <?php endif; ?>
+            <?php endif; ?>
             </span>
         <?php endif; ?>
     </td>
-    <td class="col qty">
+    <td class="col qty" data-th="<?php echo $this->escapeHtml(__('Qty Invoiced')); ?>">
         <span class="qty summary"><?php echo $_item->getQty()*1 ?></span>
     </td>
-    <td class="col subtotal">
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-            <span class="price-excl-tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-price">
-                    <?php endif; ?>
-                        <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
+    <td class="col subtotal" data-th="<?php echo $this->escapeHtml(__('Subtotal')); ?>">
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
+            <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
+                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($this->getItem()); ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
                 <?php else: ?>
                     <span class="cart-price">
                 <?php endif; ?>
-
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
-                    <?php else: ?>
-                        <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
-                    <?php endif; ?>
-
-                </span>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?>
+                <?php else: ?>
+                    <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxRowDisposition()) ?>
+                <?php endif; ?>
+                    </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-
-                    <span class="cart-tax-info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
+                    <span class="cart-tax-info" id="subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
                         <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
                             <?php endforeach; ?>
-                            </small>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></small></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                             <small>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
                             </small>
                         <?php endif; ?>
                     </span>
 
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                            <span class="nobr"><?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?></span>
+                        <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                            <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?></span>
                         </span>
                     <?php endif; ?>
                 <?php endif; ?>
             </span>
-            <br />
         <?php endif; ?>
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-            <span class="price-incl-tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                   <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-price">
-                    <?php endif; ?>
-                        <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
-                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($this->getItem()); ?>
+
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
+            <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
                 <?php else: ?>
                     <span class="cart-price">
                 <?php endif; ?>
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?>
-                    <?php else: ?>
-                        <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxRowDisposition()) ?>
-                    <?php endif; ?>
 
-                </span>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
+                <?php else: ?>
+                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
+                <?php endif; ?>
+                    </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-
-                    <span class="cart-tax-info" id="subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
-                        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
-                            <?php endforeach; ?>
-                            </small>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></small></span>
-                            <?php endforeach; ?>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
-                            <?php endforeach; ?>
-                            </small>
-                        <?php endif; ?>
+                    <span class="cart-tax-info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                    <?php endforeach; ?>
+                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
+                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
+                    <?php endforeach; ?>
+                <?php endif; ?>
                     </span>
 
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                            <span class="nobr"><?php echo __('Total incl. tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$this->getItem()->getWeeeTaxAppliedRowAmount()); ?></span>
+                        <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                            <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><<?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?></span>
                         </span>
                     <?php endif; ?>
                 <?php endif; ?>
-
             </span>
-        <?php endif; ?>
+         <?php endif; ?>
     </td>
 </tr>
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/items.phtml b/app/code/Magento/Sales/view/frontend/templates/order/items.phtml
index e71956e9ec85d8b02189c8f1b1974cac0a76e88f..8bab5f6305a1c0fefc14c4044a331dca1e188374 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/items.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/items.phtml
@@ -24,8 +24,8 @@
 ?>
 <?php $_order = $this->getOrder() ?>
 <?php $_giftMessage; ?>
-<div class="wrapper table order items">
-    <table class="data table order items" id="my-orders-table" summary="<?php echo __('Items Ordered') ?>">
+<div class="table-wrapper order-items">
+    <table class="data table table-order-items" id="my-orders-table" summary="<?php echo __('Items Ordered') ?>">
         <caption class="table caption"><?php echo __('Items Ordered') ?></caption>
         <thead>
             <tr>
@@ -48,7 +48,7 @@
             <tbody>
                 <?php echo $this->getItemHtml($_item) ?>
                 <?php if ($this->helper('Magento\GiftMessage\Helper\Message')->getIsMessagesAvailable('order_item', $_item) && $_item->getGiftMessageId()): ?>
-                <tr id="order-item-gift-message-<?php echo $_item->getId() ?>" role="region" aria-expanded="false" tabindex="-1" style="display:none;">
+                <tr id="order-item-gift-message-<?php echo $_item->getId() ?>" role="region" aria-expanded="false" tabindex="-1" style="display: none;">
                     <?php $_giftMessage = $this->helper('Magento\GiftMessage\Helper\Message')->getGiftMessageForEntity($_item); ?>
                     <td class="col message" colspan="7">
                         <div class="gift message details">
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/items/renderer/default.phtml b/app/code/Magento/Sales/view/frontend/templates/order/items/renderer/default.phtml
index 08cf3d7ad5645b0ab2de671ee722ccc673b8f03a..f4e97fb4766c862eea365e7112d00ce8ee2935be 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/items/renderer/default.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/items/renderer/default.phtml
@@ -27,8 +27,8 @@ $_item = $this->getItem();
 $_weeeHelper = $this->helper('Magento\Weee\Helper\Data');
 ?>
 <tr id="order-item-row-<?php echo $_item->getId() ?>">
-    <td class="col name">
-        <strong class="product name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
+    <td class="col name" data-th="<?php echo $this->escapeHtml(__('Product Name')); ?>">
+        <strong class="product name product-item-name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
         <?php if($_options = $this->getItemOptions()): ?>
         <dl class="item options">
         <?php foreach ($_options as $_option) : ?>
@@ -69,240 +69,196 @@ $_weeeHelper = $this->helper('Magento\Weee\Helper\Data');
             </a>
         <?php endif; ?>
     </td>
-    <td class="col sku"><?php echo $this->prepareSku($this->getSku()) ?></td>
-    <td class="col price">
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-            <span class="price-excl-tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-price">
-                    <?php endif; ?>
-                        <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
+    <td class="col sku" data-th="<?php echo $this->escapeHtml(__('SKU')); ?>"><?php echo $this->prepareSku($this->getSku()) ?></td>
+    <td class="col price" data-th="<?php echo $this->escapeHtml(__('Price')); ?>">
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
+            <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
+                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
+                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
                 <?php else: ?>
                     <span class="cart-price">
                 <?php endif; ?>
-
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
-                    <?php else: ?>
-                        <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
-                    <?php endif; ?>
-                </span>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php echo $this->getOrder()->formatPrice($_incl+$_weeeHelper->getWeeeTaxInclTax($this->getItem())); ?>
+                <?php else: ?>
+                    <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
+                <?php endif; ?>
+                    </span>
 
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-
-                    <span class="cart-tax-info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
+                    <span class="cart-tax-info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
                         <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
-                            </small>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?></small></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
-                            </small>
                         <?php endif; ?>
                     </span>
 
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
-                            <span class="nobr"><?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?></span>
+                        <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
+                            <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$_weeeHelper->getWeeeTaxInclTax($this->getItem())); ?></span>
                         </span>
                     <?php endif; ?>
                 <?php endif; ?>
             </span>
         <?php endif; ?>
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-            <span class="price-incl-tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                   <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-price">
-                    <?php endif; ?>
-                        <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
-                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($this->getItem()); ?>
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
-                <?php else: ?>
-                    <span class="cart-price">
-                <?php endif; ?>
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php echo $this->getOrder()->formatPrice($_incl+$_weeeHelper->getWeeeTaxInclTax($this->getItem())); ?>
-                    <?php else: ?>
-                        <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxDisposition()) ?>
-                    <?php endif; ?>
-                </span>
 
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
+            <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+            <?php else: ?>
+                <span class="cart-price">
+            <?php endif; ?>
 
-                    <span class="cart-tax-info" id="unit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
-                        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
-                            <?php endforeach; ?>
-                            </small>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></small></span>
-                            <?php endforeach; ?>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['amount_incl_tax']); ?></span>
-                            <?php endforeach; ?>
-                            </small>
-                        <?php endif; ?>
-                    </span>
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?>
+            <?php else: ?>
+                <?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()) ?>
+            <?php endif; ?>
+                </span>
 
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#unit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
-                            <span class="nobr"><?php echo __('Total incl. tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$_weeeHelper->getWeeeTaxInclTax($this->getItem())); ?></span>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
-            </span>
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+                <span class="cart-tax-info" id="eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
+                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                        <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                            <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                        <?php endforeach; ?>
+                    <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['amount']); ?></span>
+                    <?php endforeach; ?>
+            <?php endif; ?>
+                </span>
+
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#eunit-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'
+                    <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getPrice()+$this->getItem()->getWeeeTaxAppliedAmount()+$this->getItem()->getWeeeTaxDisposition()); ?></span>
+                </span>
+            <?php endif; ?>
+        <?php endif; ?>
+        </span>
         <?php endif; ?>
     </td>
-    <td class="col qty">
-        <ul class="qty summary items">
+    <td class="col qty" data-th="<?php echo $this->escapeHtml(__('Qty')); ?>">
+        <ul class="items-qty">
         <?php if ($this->getItem()->getQtyOrdered() > 0): ?>
-            <li class="item"><span class="label"><?php echo __('Ordered'); ?></span><strong><?php echo $this->getItem()->getQtyOrdered()*1 ?></strong></li>
+            <li class="item">
+                <span class="title"><?php echo __('Ordered'); ?></span>
+                <span class="content"><?php echo $this->getItem()->getQtyOrdered()*1 ?></span>
+            </li>
         <?php endif; ?>
         <?php if ($this->getItem()->getQtyShipped() > 0): ?>
-            <li class="item"><span class="label"><?php echo __('Shipped'); ?></span><strong><?php echo $this->getItem()->getQtyShipped()*1 ?></strong></li>
+            <li class="item">
+                <span class="title"><?php echo __('Shipped'); ?></span>
+                <span class="content"><?php echo $this->getItem()->getQtyShipped()*1 ?></span>
+            </li>
         <?php endif; ?>
         <?php if ($this->getItem()->getQtyCanceled() > 0): ?>
-            <li class="item"><span class="label"><?php echo __('Canceled'); ?></span><strong><?php echo $this->getItem()->getQtyCanceled()*1 ?></strong></li>
+            <li class="item">
+                <span class="title"><?php echo __('Canceled'); ?></span>
+                <span class="content"><?php echo $this->getItem()->getQtyCanceled()*1 ?></span>
+            </li>
         <?php endif; ?>
         <?php if ($this->getItem()->getQtyRefunded() > 0): ?>
-            <li class="item"><span class="label"><?php echo __('Refunded'); ?></span><strong><?php echo $this->getItem()->getQtyRefunded()*1 ?></strong></li>
+            <li class="item">
+                <span class="title"><?php echo __('Refunded'); ?></span>
+                <span class="content"><?php echo $this->getItem()->getQtyRefunded()*1 ?></span>
+            </li>
         <?php endif; ?>
         </ul>
     </td>
-    <td class="col subtotal">
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
-            <span class="price-excl-tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-price">
-                    <?php endif; ?>
-                        <span class="label"><?php echo __('Excl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
+    <td class="col subtotal" data-th="<?php echo $this->escapeHtml(__('Subtotal')); ?>">
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
+            <span class="incl tax" data-th="<?php echo $this->escapeHtml(__('Incl. Tax')); ?>">
+                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($this->getItem()); ?>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
                 <?php else: ?>
                     <span class="cart-price">
                 <?php endif; ?>
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
+                        <?php echo $this->getOrder()->formatPrice($_incl+$_weeeHelper->getRowWeeeTaxInclTax($this->getItem())); ?>
                     <?php else: ?>
-                        <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
+                        <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxRowDisposition()) ?>
                     <?php endif; ?>
-                </span>
-
+                    </span>
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
-
-                    <span class="cart-tax-info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
+                    <span class="cart-tax-info" id="subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
                         <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
-                            </small>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></small></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
                         <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
                             <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                                <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
                             <?php endforeach; ?>
-                            </small>
                         <?php endif; ?>
                     </span>
 
                     <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                            <span class="nobr"><?php echo __('Total'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?></span>
+                        <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                            <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total incl. tax')); ?>"><?php echo $this->getOrder()->formatPrice($_incl+$_weeeHelper->getRowWeeeTaxInclTax($this->getItem())); ?></span>
                         </span>
                     <?php endif; ?>
                 <?php endif; ?>
             </span>
-            <br />
         <?php endif; ?>
-        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceInclTax()): ?>
-            <span class="price-incl-tax">
-                <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices()): ?>
-                   <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-price">
-                    <?php endif; ?>
-                        <span class="label"><?php echo __('Incl. Tax'); ?>:</span>
-                    <?php if (!$this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        </span>
-                    <?php endif; ?>
-                <?php endif; ?>
-                <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($this->getItem()); ?>
+
+        <?php if ($this->helper('Magento\Tax\Helper\Data')->displaySalesBothPrices() || $this->helper('Magento\Tax\Helper\Data')->displaySalesPriceExclTax()): ?>
+            <span class="excl tax" data-th="<?php echo $this->escapeHtml(__('Excl. Tax')); ?>">
                 <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+            <?php else: ?>
+                <span class="cart-price">
+            <?php endif; ?>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?>
                 <?php else: ?>
-                    <span class="cart-price">
+                    <?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()) ?>
                 <?php endif; ?>
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(array(0, 1, 4), 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <?php echo $this->getOrder()->formatPrice($_incl+$_weeeHelper->getRowWeeeTaxInclTax($this->getItem())); ?>
-                    <?php else: ?>
-                        <?php echo $this->getOrder()->formatPrice($_incl-$this->getItem()->getWeeeTaxRowDisposition()) ?>
-                    <?php endif; ?>
                 </span>
 
-                <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+            <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem())): ?>
+                <span class="cart-tax-info" id="esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display: none;">
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                    <?php endforeach; ?>
+                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                    <?php endforeach; ?>
+                <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
+                        <span class="weee" data-th="<?php echo $tax['title']; ?>"><?php echo $this->getOrder()->formatPrice($tax['row_amount']); ?></span>
+                    <?php endforeach; ?>
+                <?php endif; ?>
+                </span>
 
-                    <span class="cart-tax-info" id="subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>" style="display:none;">
-                        <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(1, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
-                            <?php endforeach; ?>
-                            </small>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><small><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></small></span>
-                            <?php endforeach; ?>
-                        <?php elseif ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(4, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                            <small>
-                            <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($this->getItem()) as $tax): ?>
-                                <span class="nobr"><?php echo $tax['title']; ?>: <?php echo $this->getOrder()->formatPrice($tax['row_amount_incl_tax']); ?></span>
-                            <?php endforeach; ?>
-                            </small>
-                        <?php endif; ?>
+                <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
+                    <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#esubtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
+                        <span class="weee" data-th="<?php echo $this->escapeHtml(__('Total')); ?>"><?php echo $this->getOrder()->formatPrice($this->getItem()->getRowTotal()+$this->getItem()->getWeeeTaxAppliedRowAmount()+$this->getItem()->getWeeeTaxRowDisposition()); ?></span>
                     </span>
-
-                    <?php if ($this->helper('Magento\Weee\Helper\Data')->typeOfDisplay(2, 'sales') && (float)$this->getItem()->getWeeeTaxAppliedAmount()): ?>
-                        <span class="cart-tax-total" data-tax-toggle='{"itemTaxId" : "#subtotal-item-tax-details<?php echo $this->getItem()->getId(); ?>"}'>
-                            <span class="nobr"><?php echo __('Total incl. tax'); ?>:<br /> <?php echo $this->getOrder()->formatPrice($_incl+$_weeeHelper->getRowWeeeTaxInclTax($this->getItem())); ?></span>
-                        </span>
-                    <?php endif; ?>
                 <?php endif; ?>
+            <?php endif; ?>
             </span>
         <?php endif; ?>
     </td>
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/order_comments.phtml b/app/code/Magento/Sales/view/frontend/templates/order/order_comments.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..d09f03d81bba6df6655a09fc6094f6d72aa75c43
--- /dev/null
+++ b/app/code/Magento/Sales/view/frontend/templates/order/order_comments.phtml
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+?>
+<?php /** @var  $this \Magento\Sales\Block\Order\View*/?>
+
+<?php $_history = $this->getOrder()->getVisibleStatusHistory() ?>
+<?php if (count($_history)): ?>
+    <div class="block block-order-details-comments">
+        <div class="block-title"><strong><?php echo __('About Your Order') ?></strong></div>
+        <div class="block-content">
+            <dl class="order-comments">
+                <?php foreach ($_history as $_historyItem): ?>
+                    <dt class="comment-date"><?php echo $this->formatDate($_historyItem->getCreatedAtStoreDate(), 'medium', true) ?></dt>
+                    <dd class="comment-content"><?php echo $this->escapeHtml($_historyItem->getComment()) ?></dd>
+                <?php endforeach; ?>
+            </dl>
+
+        </div>
+    </div>
+<?php endif; ?>
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/order_date.phtml b/app/code/Magento/Sales/view/frontend/templates/order/order_date.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..02e9b2f83a195e6f0efac1119c3afd113308d646
--- /dev/null
+++ b/app/code/Magento/Sales/view/frontend/templates/order/order_date.phtml
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+?>
+
+<div class="order-date"><?php echo __('<span class="label">Order Date:</span> %1', '<date>' . $this->formatDate($this->getOrder()->getCreatedAtStoreDate(), 'long') . '</date>' ) ?></div>
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/order_rss.phtml b/app/code/Magento/Sales/view/frontend/templates/order/order_rss.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..705fb178493c633f6e216cb5255cd89965e2641e
--- /dev/null
+++ b/app/code/Magento/Sales/view/frontend/templates/order/order_rss.phtml
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+?>
+<?php /** @var $this \Magento\Sales\Block\Order\Info */ ?>
+<?php echo $this->getStatusHistoryRssUrl($this->getOrder()) ?>
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/order_status.phtml b/app/code/Magento/Sales/view/frontend/templates/order/order_status.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..585071c2fa6a6816b55d23b4fdae178603a4e1cb
--- /dev/null
+++ b/app/code/Magento/Sales/view/frontend/templates/order/order_status.phtml
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+?>
+<?php /** @var $this \Magento\Sales\Block\Order\Info */ ?>
+
+<span class="order-status"><?php echo $this->getOrder()->getStatusLabel() ?></span>
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/print.phtml b/app/code/Magento/Sales/view/frontend/templates/order/print.phtml
index 0f6e73322d5981254eebfa9732a4aeb63721edb4..00da52142659f06e46d7bce24b269b6586ec2a67 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/print.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/print.phtml
@@ -65,8 +65,8 @@
     </div>
 </div>
 
-<div class="order details items">
-    <div class="order subtitle caption">
+<div class="order-details-items">
+    <div class="order-title">
         <strong><?php echo __('Items Ordered') ?></strong>
     </div>
     <table class="data table order items" id="my-orders-table">
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/print/creditmemo.phtml b/app/code/Magento/Sales/view/frontend/templates/order/print/creditmemo.phtml
index dd81437c0a2b26942d214229d451cb8f125f1a70..5dc5c30828f6228d62e3253b0a8fe8863313c498 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/print/creditmemo.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/print/creditmemo.phtml
@@ -71,7 +71,7 @@
             </div>
         </div>
         <?php endif; ?>
-        <div class="block order payment method">
+        <div class="block order payment-method">
             <div class="title">
                 <strong><?php echo __('Payment Method') ?></strong>
             </div>
@@ -79,10 +79,9 @@
                 <?php echo $this->getPaymentInfoHtml() ?>
             </div>
         </div>
-
     </div>
-    <div class="order details items">
-        <div class="order subtitle caption">
+    <div class="order-details-items">
+        <div class="order-title">
             <strong><?php echo __('Items Refunded') ?></strong>
         </div>
         <table class="data table order items" id="my-refund-table-<?php echo $_creditmemo->getId(); ?>">
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/print/invoice.phtml b/app/code/Magento/Sales/view/frontend/templates/order/print/invoice.phtml
index d56dcc43c6da5f8c181664b4b6b079b4ed1e3930..7a5813f5a0a0dfe68812efc12370a8063ca68190 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/print/invoice.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/print/invoice.phtml
@@ -70,7 +70,7 @@
         </div>
     </div>
     <?php endif; ?>
-    <div class="block order payment method">
+    <div class="block order payment-method">
         <div class="title">
             <strong><?php echo __('Payment Method') ?></strong>
         </div>
@@ -79,8 +79,8 @@
         </div>
     </div>
 </div>
-<div class="order details items">
-    <div class="order subtitle caption">
+<div class="order-details-items">
+    <div class="order-title">
         <strong><?php echo __('Items Invoiced') ?></strong>
     </div>
     <table class="data table order items" id="my-invoice-table-<?php echo $_invoice->getId(); ?>">
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/print/shipment.phtml b/app/code/Magento/Sales/view/frontend/templates/order/print/shipment.phtml
index 051a90c2324d1fd86ab79ef7c74fd8d00a353076..bf2db55c1287fc4280e0bdd955cd9e1118955d7d 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/print/shipment.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/print/shipment.phtml
@@ -81,7 +81,7 @@
             <?php endif; ?>
         </div>
 
-        <div class="block order payment method">
+        <div class="block order payment-method">
             <div class="title">
                 <strong><?php echo __('Payment Method') ?></strong>
             </div>
@@ -91,8 +91,8 @@
         </div>
 
     </div>
-    <div class="order details items">
-        <div class="order subtitle caption">
+    <div class="order-details-items">
+        <div class="order-title">
             <strong><?php echo __('Items Shipped') ?></strong>
         </div>
         <table class="data table order items" id="my-shipment-table-<?php echo $this->getObjectData($shipment, 'id') ?>">
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/recent.phtml b/app/code/Magento/Sales/view/frontend/templates/order/recent.phtml
index 0e59cad70e4bfc0b779731331fb4e7e2862f8780..caf54b3b9b3326f6eebc17c8a979ecedb738c1b8 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/recent.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/recent.phtml
@@ -22,9 +22,9 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 ?>
-<div class="block dashboard orders">
+<div class="block block-dashboard-orders">
 <?php $_orders = $this->getOrders(); ?>
-    <div class="order title">
+    <div class="block-title order">
         <strong><?php echo __('Recent Orders') ?></strong>
         <?php if( sizeof($_orders->getItems()) > 0 ): ?>
             <a class="action view" href="<?php echo $this->getUrl('sales/order/history') ?>">
@@ -32,31 +32,31 @@
             </a>
         <?php endif; ?>
     </div>
-    <div class="content">
+    <div class="block-content">
     <?php echo $this->getChildHtml()?>
     <?php if( sizeof($_orders->getItems()) > 0 ): ?>
-        <div class="wrapper table orders recent">
-            <table class="data table orders recent" id="my-orders-table">
+        <div class="table-wrapper orders-recent">
+            <table class="data table table-order-items recent" id="my-orders-table">
                 <caption class="table caption"><?php echo __('Recent Orders') ?></caption>
                 <thead>
                     <tr>
-                        <th class="col id"><?php echo __('Order #') ?></th>
-                        <th class="col date"><?php echo __('Date') ?></th>
-                        <th class="col shipping"><?php echo __('Ship To') ?></th>
-                        <th class="col total"><?php echo __('Order Total') ?></th>
-                        <th class="col status"><?php echo __('Status') ?></th>
-                        <th class="col actions">&nbsp;</th>
+                        <th scope="col" class="col id"><?php echo __('Order #') ?></th>
+                        <th scope="col" class="col date"><?php echo __('Date') ?></th>
+                        <th scope="col" class="col shipping"><?php echo __('Ship To') ?></th>
+                        <th scope="col" class="col total"><?php echo __('Order Total') ?></th>
+                        <th scope="col" class="col status"><?php echo __('Status') ?></th>
+                        <th scope="col" class="col actions">&nbsp;</th>
                     </tr>
                 </thead>
                 <tbody>
                     <?php foreach ($_orders as $_order): ?>
                         <tr>
-                            <td class="col id"><?php echo $_order->getRealOrderId() ?></td>
-                            <td class="col date"><?php echo $this->formatDate($_order->getCreatedAtStoreDate()) ?></td>
-                            <td class="col shipping"><?php echo $_order->getShippingAddress() ? $this->escapeHtml($_order->getShippingAddress()->getName()) : '&nbsp;' ?></td>
-                            <td class="col total"><?php echo $_order->formatPrice($_order->getGrandTotal()) ?></td>
-                            <td class="col status"><em><?php echo $_order->getStatusLabel() ?></em></td>
-                            <td class="col actions">
+                            <td data-th="<?php echo $this->escapeHtml(__('Order #')) ?>" class="col id"><?php echo $_order->getRealOrderId() ?></td>
+                            <td data-th="<?php echo $this->escapeHtml(__('Date')) ?>" class="col date"><?php echo $this->formatDate($_order->getCreatedAtStoreDate()) ?></td>
+                            <td data-th="<?php echo $this->escapeHtml(__('Ship To')) ?>" class="col shipping"><?php echo $_order->getShippingAddress() ? $this->escapeHtml($_order->getShippingAddress()->getName()) : '&nbsp;' ?></td>
+                            <td data-th="<?php echo $this->escapeHtml(__('Order Total')) ?>" class="col total"><?php echo $_order->formatPrice($_order->getGrandTotal()) ?></td>
+                            <td data-th="<?php echo $this->escapeHtml(__('Status')) ?>" class="col status"><?php echo $_order->getStatusLabel() ?></td>
+                            <td data-th="<?php echo $this->escapeHtml(__('Actions')) ?>" class="col actions">
                                 <a href="<?php echo $this->getViewUrl($_order) ?>" class="action view">
                                     <span><?php echo __('View Order') ?></span>
                                 </a>
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/shipment/items/renderer/default.phtml b/app/code/Magento/Sales/view/frontend/templates/order/shipment/items/renderer/default.phtml
index f82b1f01d2f0451b1237a5668270c6c22efd4505..a5f1ceecc0ca140a883b1d8d0b10a63efa167edf 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/shipment/items/renderer/default.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/shipment/items/renderer/default.phtml
@@ -25,8 +25,8 @@
 <?php $_item = $this->getItem() ?>
 <?php $_order = $this->getItem()->getOrderItem()->getOrder() ?>
 <tr id="order-item-row-<?php echo $_item->getId() ?>">
-    <td class="col name">
-        <strong class="product name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
+    <td class="col name" data-th="<?php echo $this->escapeHtml(__('Product Name')); ?>">
+        <strong class="product name product-item-name"><?php echo $this->escapeHtml($_item->getName()) ?></strong>
         <?php if($_options = $this->getItemOptions()): ?>
         <dl class="item options">
         <?php foreach ($_options as $_option) : ?>
@@ -65,6 +65,6 @@
             </a>
         <?php endif; ?>
     </td>
-    <td class="col sku"><?php echo $this->prepareSku($this->getSku()) ?></td>
-    <td class="col qty"><?php echo $_item->getQty()*1 ?></td>
+    <td class="col sku" data-th="<?php echo $this->escapeHtml(__('SKU')); ?>"><?php echo $this->prepareSku($this->getSku()) ?></td>
+    <td class="col qty" data-th="<?php echo $this->escapeHtml(__('Qty Shipped')); ?>"><?php echo $_item->getQty()*1 ?></td>
 </tr>
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/view.phtml b/app/code/Magento/Sales/view/frontend/templates/order/view.phtml
index 885e151dd5b7d2d068f9bb0e6e37244e49735031..096ef21e0f70d1175d5c063917740eaf20a1c99b 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/view.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/view.phtml
@@ -23,10 +23,10 @@
  */
 ?>
 <?php /** @var  $this \Magento\Sales\Block\Order\View*/?>
-<div class="order details items">
+<div class="order-details-items ordered">
     <?php $_order = $this->getOrder() ?>
 
-    <div class="order subtitle caption">
+    <div class="order-title">
         <strong><?php echo __('Items Ordered') ?></strong>
         <?php if ($_order->getTracksCollection()->count()) : ?>
             <?php echo $this->getChildHtml('tracking-info-link') ?>
@@ -36,28 +36,19 @@
     <?php echo $this->getChildHtml('order_items') ?>
 
     <?php if($this->helper('Magento\GiftMessage\Helper\Message')->getIsMessagesAvailable('order', $_order) && $_order->getGiftMessageId()): ?>
-    <div class="order additional details gift">
-        <div class="order subtitle caption"><strong><?php echo __('Gift Message for This Order') ?></strong></div>
+    <div class="block block-order-details-additional">
+        <div class="block-title"><strong><?php echo __('Gift Message for This Order') ?></strong></div>
         <?php $_giftMessage=$this->helper('Magento\GiftMessage\Helper\Message')->getGiftMessageForEntity($_order); ?>
-        <dl class="gift message">
-            <dt class="gift sender"><strong class="label"><?php echo __('From:') ?></strong> <?php echo $this->escapeHtml($_giftMessage->getSender()) ?></dt>
-            <dt class="gift recipient"><strong class="label"><?php echo __('To:') ?></strong> <?php echo $this->escapeHtml($_giftMessage->getRecipient()) ?></dt>
-            <dd class="message text"><?php echo $this->helper('Magento\GiftMessage\Helper\Message')->getEscapedGiftMessage($_order) ?></dd>
-        </dl>
-    </div>
-    <?php endif; ?>
-    <?php $_history = $this->getOrder()->getVisibleStatusHistory() ?>
-    <?php if (count($_history)): ?>
-    <div class="order additional details comments">
-        <div class="order subtitle caption"><strong><?php echo __('About Your Order') ?></strong></div>
-        <dl class="order comments">
-            <?php foreach ($_history as $_historyItem): ?>
-                <dt class="comment date"><?php echo $this->formatDate($_historyItem->getCreatedAtStoreDate(), 'medium', true) ?></dt>
-                <dd class="comment text"><?php echo $this->escapeHtml($_historyItem->getComment()) ?></dd>
-            <?php endforeach; ?>
-        </dl>
+        <div class="block-content">
+            <dl class="gift-message">
+                <dt class="gift-sender"><strong class="label"><?php echo __('From:') ?></strong> <?php echo $this->escapeHtml($_giftMessage->getSender()) ?></dt>
+                <dt class="gift-recipient"><strong class="label"><?php echo __('To:') ?></strong> <?php echo $this->escapeHtml($_giftMessage->getRecipient()) ?></dt>
+                <dd class="gift-message-text"><?php echo $this->helper('Magento\GiftMessage\Helper\Message')->getEscapedGiftMessage($_order) ?></dd>
+            </dl>
+        </div>
     </div>
     <?php endif; ?>
+
     <div class="actions-toolbar">
         <div class="secondary">
             <a class="action back" href="<?php echo $this->getBackUrl() ?>">
diff --git a/app/code/Magento/SalesRule/Model/RulesApplier.php b/app/code/Magento/SalesRule/Model/RulesApplier.php
new file mode 100644
index 0000000000000000000000000000000000000000..a1138962db5ee3842f9da79bad0f18709b25aa78
--- /dev/null
+++ b/app/code/Magento/SalesRule/Model/RulesApplier.php
@@ -0,0 +1,253 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\SalesRule\Model;
+
+use Magento\Sales\Model\Quote\Address;
+
+/**
+ * Class RulesApplier
+ * @package Magento\SalesRule\Model\Validator
+ */
+class RulesApplier
+{
+    /**
+     * Application Event Dispatcher
+     *
+     * @var \Magento\Framework\Event\ManagerInterface
+     */
+    protected $_eventManager;
+
+    /**
+     * @var \Magento\SalesRule\Model\Utility
+     */
+    protected $validatorUtility;
+
+    /**
+     * @param \Magento\SalesRule\Model\Rule\Action\Discount\CalculatorFactory $calculatorFactory
+     * @param \Magento\Framework\Event\ManagerInterface $eventManager
+     * @param \Magento\SalesRule\Model\Utility $utility
+     */
+    public function __construct(
+        \Magento\SalesRule\Model\Rule\Action\Discount\CalculatorFactory $calculatorFactory,
+        \Magento\Framework\Event\ManagerInterface $eventManager,
+        \Magento\SalesRule\Model\Utility $utility
+    ) {
+        $this->calculatorFactory = $calculatorFactory;
+        $this->validatorUtility = $utility;
+        $this->_eventManager = $eventManager;
+    }
+
+    /**
+     * Apply rules to current order item
+     *
+     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
+     * @param \Magento\SalesRule\Model\Resource\Rule\Collection $rules
+     * @param bool $skipValidation
+     * @param mixed $couponCode
+     * @return array
+     */
+    public function applyRules($item, $rules, $skipValidation, $couponCode)
+    {
+        $address = $item->getAddress();
+        $appliedRuleIds = array();
+        /* @var $rule \Magento\SalesRule\Model\Rule */
+        foreach ($rules as $rule) {
+            if (!$this->validatorUtility->canProcessRule($rule, $address)) {
+                continue;
+            }
+
+            if (!$skipValidation && !$rule->getActions()->validate($item)) {
+                continue;
+            }
+
+            $this->applyRule($item, $rule, $address, $couponCode);
+            $appliedRuleIds[$rule->getRuleId()] = $rule->getRuleId();
+
+            if ($rule->getStopRulesProcessing()) {
+                break;
+            }
+        }
+
+        return $appliedRuleIds;
+    }
+
+    /**
+     * Add rule discount description label to address object
+     *
+     * @param Address $address
+     * @param \Magento\SalesRule\Model\Rule $rule
+     * @return $this
+     */
+    public function addDiscountDescription($address, $rule)
+    {
+        $description = $address->getDiscountDescriptionArray();
+        $ruleLabel = $rule->getStoreLabel($address->getQuote()->getStore());
+        $label = '';
+        if ($ruleLabel) {
+            $label = $ruleLabel;
+        } else {
+            if (strlen($address->getCouponCode())) {
+                $label = $address->getCouponCode();
+            }
+        }
+
+        if (strlen($label)) {
+            $description[$rule->getId()] = $label;
+        }
+
+        $address->setDiscountDescriptionArray($description);
+
+        return $this;
+    }
+
+    /**
+     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
+     * @param \Magento\SalesRule\Model\Rule $rule
+     * @param \Magento\Sales\Model\Quote\Address $address
+     * @param mixed $couponCode
+     * @return $this
+     */
+    protected function applyRule($item, $rule, $address, $couponCode)
+    {
+        $discountData = $this->getDiscountData($item, $rule);
+        $this->setDiscountData($discountData, $item);
+
+        $this->maintainAddressCouponCode($address, $rule, $couponCode);
+        $this->addDiscountDescription($address, $rule);
+
+        return $this;
+    }
+
+    /**
+     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
+     * @param \Magento\SalesRule\Model\Rule $rule
+     * @return \Magento\SalesRule\Model\Rule\Action\Discount\Data
+     */
+    protected function getDiscountData($item, $rule)
+    {
+        $qty = $this->validatorUtility->getItemQty($item, $rule);
+
+        $discountCalculator = $this->calculatorFactory->create($rule->getSimpleAction());
+        $qty = $discountCalculator->fixQuantity($qty, $rule);
+        $discountData = $discountCalculator->calculate($rule, $item, $qty);
+
+        $this->eventFix($discountData, $item, $rule, $qty);
+        $this->validatorUtility->deltaRoundingFix($discountData, $item);
+
+        /**
+         * We can't use row total here because row total not include tax
+         * Discount can be applied on price included tax
+         */
+
+        $this->validatorUtility->minFix($discountData, $item, $qty);
+
+        return $discountData;
+    }
+
+    /**
+     * @param \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData
+     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
+     * @return $this
+     */
+    protected function setDiscountData($discountData, $item)
+    {
+        $item->setDiscountAmount($discountData->getAmount());
+        $item->setBaseDiscountAmount($discountData->getBaseAmount());
+        $item->setOriginalDiscountAmount($discountData->getOriginalAmount());
+        $item->setBaseOriginalDiscountAmount($discountData->getBaseOriginalAmount());
+
+        return $this;
+    }
+
+    /**
+     * Set coupon code to address if $rule contains validated coupon
+     *
+     * @param Address $address
+     * @param \Magento\SalesRule\Model\Rule $rule
+     * @param mixed $couponCode
+     * @return $this
+     */
+    public function maintainAddressCouponCode($address, $rule, $couponCode)
+    {
+        /*
+        Rule is a part of rules collection, which includes only rules with 'No Coupon' type or with validated coupon.
+        As a result, if rule uses coupon code(s) ('Specific' or 'Auto' Coupon Type), it always contains validated coupon
+        */
+        if ($rule->getCouponType() != \Magento\SalesRule\Model\Rule::COUPON_TYPE_NO_COUPON) {
+            $address->setCouponCode($couponCode);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Fire event to allow overwriting of discount amounts
+     *
+     * @param \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData
+     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
+     * @param \Magento\SalesRule\Model\Rule $rule
+     * @param float $qty
+     * @return $this
+     */
+    protected function eventFix(
+        \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData,
+        \Magento\Sales\Model\Quote\Item\AbstractItem $item,
+        \Magento\SalesRule\Model\Rule $rule,
+        $qty
+    ) {
+        $quote = $item->getQuote();
+        $address = $item->getAddress();
+
+        $this->_eventManager->dispatch(
+            'salesrule_validator_process',
+            array(
+                'rule' => $rule,
+                'item' => $item,
+                'address' => $address,
+                'quote' => $quote,
+                'qty' => $qty,
+                'result' => $discountData
+            )
+        );
+
+        return $this;
+    }
+
+    /**
+     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
+     * @param int[] $appliedRuleIds
+     * @return $this
+     */
+    public function setAppliedRuleIds(\Magento\Sales\Model\Quote\Item\AbstractItem $item, array $appliedRuleIds)
+    {
+        $address = $item->getAddress();
+        $quote = $item->getQuote();
+
+        $item->setAppliedRuleIds(join(',', $appliedRuleIds));
+        $address->setAppliedRuleIds($this->validatorUtility->mergeIds($address->getAppliedRuleIds(), $appliedRuleIds));
+        $quote->setAppliedRuleIds($this->validatorUtility->mergeIds($quote->getAppliedRuleIds(), $appliedRuleIds));
+
+        return $this;
+    }
+}
diff --git a/app/code/Magento/SalesRule/Model/Utility.php b/app/code/Magento/SalesRule/Model/Utility.php
new file mode 100644
index 0000000000000000000000000000000000000000..a3c0e1a8a62b06e7b1b8b031451725cd93cb5535
--- /dev/null
+++ b/app/code/Magento/SalesRule/Model/Utility.php
@@ -0,0 +1,268 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\SalesRule\Model;
+
+
+class Utility
+{
+    /**
+     * @var array
+     */
+    protected $_roundingDeltas = array();
+
+    /**
+     * @var array
+     */
+    protected $_baseRoundingDeltas = array();
+
+    /**
+     * @var \Magento\SalesRule\Model\Resource\Coupon\UsageFactory
+     */
+    protected $usageFactory;
+
+    /**
+     * @var \Magento\SalesRule\Model\CouponFactory
+     */
+    protected $couponFactory;
+
+    /**
+     * @var \Magento\SalesRule\Model\Rule\CustomerFactory
+     */
+    protected $customerFactory;
+
+    /**
+     * @param \Magento\SalesRule\Model\Resource\Coupon\UsageFactory $usageFactory
+     * @param \Magento\SalesRule\Model\CouponFactory $couponFactory
+     * @param \Magento\SalesRule\Model\Rule\CustomerFactory $customerFactory
+     */
+    public function __construct (
+        \Magento\SalesRule\Model\Resource\Coupon\UsageFactory $usageFactory,
+        \Magento\SalesRule\Model\CouponFactory $couponFactory,
+        \Magento\SalesRule\Model\Rule\CustomerFactory $customerFactory
+    ) {
+        $this->couponFactory = $couponFactory;
+        $this->customerFactory = $customerFactory;
+        $this->usageFactory = $usageFactory;
+    }
+
+    /**
+     * Check if rule can be applied for specific address/quote/customer
+     *
+     * @param \Magento\SalesRule\Model\Rule $rule
+     * @param \Magento\Sales\Model\Quote\Address $address
+     * @return bool
+     */
+    public function canProcessRule($rule, $address)
+    {
+        if ($rule->hasIsValidForAddress($address) && !$address->isObjectNew()) {
+            return $rule->getIsValidForAddress($address);
+        }
+
+        /**
+         * check per coupon usage limit
+         */
+        if ($rule->getCouponType() != \Magento\SalesRule\Model\Rule::COUPON_TYPE_NO_COUPON) {
+            $couponCode = $address->getQuote()->getCouponCode();
+            if (strlen($couponCode)) {
+                /** @var \Magento\SalesRule\Model\Coupon $coupon */
+                $coupon = $this->couponFactory->create();
+                $coupon->load($couponCode, 'code');
+                if ($coupon->getId()) {
+                    // check entire usage limit
+                    if ($coupon->getUsageLimit() && $coupon->getTimesUsed() >= $coupon->getUsageLimit()) {
+                        $rule->setIsValidForAddress($address, false);
+                        return false;
+                    }
+                    // check per customer usage limit
+                    $customerId = $address->getQuote()->getCustomerId();
+                    if ($customerId && $coupon->getUsagePerCustomer()) {
+                        $couponUsage = new \Magento\Framework\Object();
+                        $this->usageFactory->create()->loadByCustomerCoupon(
+                            $couponUsage,
+                            $customerId,
+                            $coupon->getId()
+                        );
+                        if ($couponUsage->getCouponId() &&
+                            $couponUsage->getTimesUsed() >= $coupon->getUsagePerCustomer()
+                        ) {
+                            $rule->setIsValidForAddress($address, false);
+                            return false;
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
+         * check per rule usage limit
+         */
+        $ruleId = $rule->getId();
+        if ($ruleId && $rule->getUsesPerCustomer()) {
+            $customerId = $address->getQuote()->getCustomerId();
+            $ruleCustomer = $this->customerFactory->create();
+            $ruleCustomer->loadByCustomerRule($customerId, $ruleId);
+            if ($ruleCustomer->getId()) {
+                if ($ruleCustomer->getTimesUsed() >= $rule->getUsesPerCustomer()) {
+                    $rule->setIsValidForAddress($address, false);
+                    return false;
+                }
+            }
+        }
+        $rule->afterLoad();
+        /**
+         * quote does not meet rule's conditions
+         */
+        if (!$rule->validate($address)) {
+            $rule->setIsValidForAddress($address, false);
+            return false;
+        }
+        /**
+         * passed all validations, remember to be valid
+         */
+        $rule->setIsValidForAddress($address, true);
+        return true;
+    }
+
+    /**
+     * @param \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData
+     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
+     * @param float $qty
+     * @return void
+     */
+    public function minFix(
+        \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData,
+        \Magento\Sales\Model\Quote\Item\AbstractItem $item,
+        $qty
+    ) {
+        $itemPrice = $this->getItemPrice($item);
+        $baseItemPrice = $this->getItemBasePrice($item);
+
+        $itemDiscountAmount = $item->getDiscountAmount();
+        $itemBaseDiscountAmount = $item->getBaseDiscountAmount();
+
+        $discountAmount = min($itemDiscountAmount + $discountData->getAmount(), $itemPrice * $qty);
+        $baseDiscountAmount = min($itemBaseDiscountAmount + $discountData->getBaseAmount(), $baseItemPrice * $qty);
+
+        $discountData->setAmount($discountAmount);
+        $discountData->setBaseAmount($baseDiscountAmount);
+    }
+
+    /**
+     * Process "delta" rounding
+     *
+     * @param \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData
+     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
+     * @return $this
+     */
+    public function deltaRoundingFix(
+        \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData,
+        \Magento\Sales\Model\Quote\Item\AbstractItem $item
+    ) {
+        $store = $item->getQuote()->getStore();
+        $discountAmount = $discountData->getAmount();
+        $baseDiscountAmount = $discountData->getBaseAmount();
+
+        //TODO Seems \Magento\Sales\Model\Quote\Item\AbstractItem::getDiscountPercent() returns float value
+        //that can not be used as array index
+        $percentKey = $item->getDiscountPercent();
+        if ($percentKey) {
+            $delta = isset($this->_roundingDeltas[$percentKey]) ? $this->_roundingDeltas[$percentKey] : 0;
+            $baseDelta = isset($this->_baseRoundingDeltas[$percentKey]) ? $this->_baseRoundingDeltas[$percentKey] : 0;
+
+            $discountAmount += $delta;
+            $baseDiscountAmount += $baseDelta;
+
+            $this->_roundingDeltas[$percentKey] = $discountAmount - $store->roundPrice($discountAmount);
+            $this->_baseRoundingDeltas[$percentKey] = $baseDiscountAmount - $store->roundPrice($baseDiscountAmount);
+        }
+
+        $discountData->setAmount($store->roundPrice($discountAmount));
+        $discountData->setBaseAmount($store->roundPrice($baseDiscountAmount));
+
+        return $this;
+    }
+
+    /**
+     * Return item price
+     *
+     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
+     * @return float
+     */
+    public function getItemPrice($item)
+    {
+        $price = $item->getDiscountCalculationPrice();
+        $calcPrice = $item->getCalculationPrice();
+        return $price === null ? $calcPrice : $price;
+    }
+
+    /**
+     * Return item base price
+     *
+     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
+     * @return float
+     */
+    public function getItemBasePrice($item)
+    {
+        $price = $item->getDiscountCalculationPrice();
+        return $price !== null ? $item->getBaseDiscountCalculationPrice() : $item->getBaseCalculationPrice();
+    }
+
+    /**
+     * Return discount item qty
+     *
+     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
+     * @param \Magento\SalesRule\Model\Rule $rule
+     * @return int
+     */
+    public function getItemQty($item, $rule)
+    {
+        $qty = $item->getTotalQty();
+        $discountQty = $rule->getDiscountQty();
+        return $discountQty ? min($qty, $discountQty) : $qty;
+    }
+
+    /**
+     * Merge two sets of ids
+     *
+     * @param array|string $a1
+     * @param array|string $a2
+     * @param bool $asString
+     * @return array
+     */
+    public function mergeIds($a1, $a2, $asString = true)
+    {
+        if (!is_array($a1)) {
+            $a1 = empty($a1) ? array() : explode(',', $a1);
+        }
+        if (!is_array($a2)) {
+            $a2 = empty($a2) ? array() : explode(',', $a2);
+        }
+        $a = array_unique(array_merge($a1, $a2));
+        if ($asString) {
+            $a = implode(',', $a);
+        }
+        return $a;
+    }
+}
diff --git a/app/code/Magento/SalesRule/Model/Validator.php b/app/code/Magento/SalesRule/Model/Validator.php
index 12367e76dc23821de6355fcc8529f5b84a91d0b2..c89304ffb3fe92f281e2cbf85d9d9c5a131de4d9 100644
--- a/app/code/Magento/SalesRule/Model/Validator.php
+++ b/app/code/Magento/SalesRule/Model/Validator.php
@@ -47,16 +47,6 @@ class Validator extends \Magento\Framework\Model\AbstractModel
      */
     protected $_rules;
 
-    /**
-     * @var array
-     */
-    protected $_roundingDeltas = array();
-
-    /**
-     * @var array
-     */
-    protected $_baseRoundingDeltas = array();
-
     /**
      * Defines if method \Magento\SalesRule\Model\Validator::reset() wasn't called
      * Used for clearing applied rule ids in Quote and in Address
@@ -92,41 +82,22 @@ class Validator extends \Magento\Framework\Model\AbstractModel
     protected $_collectionFactory;
 
     /**
-     * @var \Magento\SalesRule\Model\Resource\Coupon\UsageFactory
-     */
-    protected $_usageFactory;
-
-    /**
-     * @var \Magento\SalesRule\Model\CouponFactory
+     * @var \Magento\SalesRule\Model\Utility
      */
-    protected $_couponFactory;
+    protected $validatorUtility;
 
     /**
-     * @var \Magento\SalesRule\Model\Rule\CustomerFactory
+     * @var \Magento\SalesRule\Model\RulesApplier
      */
-    protected $_customerFactory;
-
-    /**
-     * @var \Magento\SalesRule\Model\Rule\Action\Discount\CalculatorFactory
-     */
-    protected $calculatorFactory;
-
-    /**
-     * Defines if rule with stop further rules is already applied
-     *
-     * @var bool
-     */
-    protected $_stopFurtherRules = false;
+    protected $rulesApplier;
 
     /**
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
-     * @param \Magento\SalesRule\Model\Resource\Coupon\UsageFactory $usageFactory
-     * @param \Magento\SalesRule\Model\Resource\Rule\CollectionFactory $collectionFactory
+     * @param Resource\Rule\CollectionFactory $collectionFactory
      * @param \Magento\Tax\Helper\Data $taxData
-     * @param \Magento\SalesRule\Model\CouponFactory $couponFactory
-     * @param \Magento\SalesRule\Model\Rule\CustomerFactory $customerFactory
-     * @param \Magento\SalesRule\Model\Rule\Action\Discount\CalculatorFactory $calculatorFactory
+     * @param Utility $utility
+     * @param RulesApplier $rulesApplier
      * @param \Magento\Framework\Model\Resource\AbstractResource $resource
      * @param \Magento\Framework\Data\Collection\Db $resourceCollection
      * @param array $data
@@ -134,22 +105,18 @@ class Validator extends \Magento\Framework\Model\AbstractModel
     public function __construct(
         \Magento\Framework\Model\Context $context,
         \Magento\Framework\Registry $registry,
-        \Magento\SalesRule\Model\Resource\Coupon\UsageFactory $usageFactory,
         \Magento\SalesRule\Model\Resource\Rule\CollectionFactory $collectionFactory,
         \Magento\Tax\Helper\Data $taxData,
-        \Magento\SalesRule\Model\CouponFactory $couponFactory,
-        \Magento\SalesRule\Model\Rule\CustomerFactory $customerFactory,
-        \Magento\SalesRule\Model\Rule\Action\Discount\CalculatorFactory $calculatorFactory,
+        \Magento\SalesRule\Model\Utility $utility,
+        \Magento\SalesRule\Model\RulesApplier $rulesApplier,
         \Magento\Framework\Model\Resource\AbstractResource $resource = null,
         \Magento\Framework\Data\Collection\Db $resourceCollection = null,
         array $data = array()
     ) {
-        $this->_usageFactory = $usageFactory;
         $this->_collectionFactory = $collectionFactory;
         $this->_taxData = $taxData;
-        $this->_couponFactory = $couponFactory;
-        $this->_customerFactory = $customerFactory;
-        $this->calculatorFactory = $calculatorFactory;
+        $this->validatorUtility = $utility;
+        $this->rulesApplier = $rulesApplier;
         parent::__construct($context, $registry, $resource, $resourceCollection, $data);
     }
 
@@ -169,12 +136,14 @@ class Validator extends \Magento\Framework\Model\AbstractModel
 
         $key = $websiteId . '_' . $customerGroupId . '_' . $couponCode;
         if (!isset($this->_rules[$key])) {
-            $this->_rules[$key] = $this->_collectionFactory->create()->setValidationFilter(
-                $websiteId,
-                $customerGroupId,
-                $couponCode
-            )->addFieldToFilter('is_active', 1)
-            ->load();
+            $this->_rules[$key] = $this->_collectionFactory->create()
+                ->setValidationFilter(
+                    $websiteId,
+                    $customerGroupId,
+                    $couponCode
+                )
+                ->addFieldToFilter('is_active', 1)
+                ->load();
         }
         return $this;
     }
@@ -190,84 +159,6 @@ class Validator extends \Magento\Framework\Model\AbstractModel
         return $this->_rules[$key];
     }
 
-    /**
-     * Check if rule can be applied for specific address/quote/customer
-     *
-     * @param \Magento\SalesRule\Model\Rule $rule
-     * @param Address $address
-     * @return bool
-     */
-    protected function _canProcessRule($rule, $address)
-    {
-        if ($rule->hasIsValidForAddress($address) && !$address->isObjectNew()) {
-            return $rule->getIsValidForAddress($address);
-        }
-
-        /**
-         * check per coupon usage limit
-         */
-        if ($rule->getCouponType() != \Magento\SalesRule\Model\Rule::COUPON_TYPE_NO_COUPON) {
-            $couponCode = $address->getQuote()->getCouponCode();
-            if (strlen($couponCode)) {
-                /** @var \Magento\SalesRule\Model\Coupon $coupon */
-                $coupon = $this->_couponFactory->create();
-                $coupon->load($couponCode, 'code');
-                if ($coupon->getId()) {
-                    // check entire usage limit
-                    if ($coupon->getUsageLimit() && $coupon->getTimesUsed() >= $coupon->getUsageLimit()) {
-                        $rule->setIsValidForAddress($address, false);
-                        return false;
-                    }
-                    // check per customer usage limit
-                    $customerId = $address->getQuote()->getCustomerId();
-                    if ($customerId && $coupon->getUsagePerCustomer()) {
-                        $couponUsage = new \Magento\Framework\Object();
-                        $this->_usageFactory->create()->loadByCustomerCoupon(
-                            $couponUsage,
-                            $customerId,
-                            $coupon->getId()
-                        );
-                        if ($couponUsage->getCouponId() &&
-                            $couponUsage->getTimesUsed() >= $coupon->getUsagePerCustomer()
-                        ) {
-                            $rule->setIsValidForAddress($address, false);
-                            return false;
-                        }
-                    }
-                }
-            }
-        }
-
-        /**
-         * check per rule usage limit
-         */
-        $ruleId = $rule->getId();
-        if ($ruleId && $rule->getUsesPerCustomer()) {
-            $customerId = $address->getQuote()->getCustomerId();
-            $ruleCustomer = $this->_customerFactory->create();
-            $ruleCustomer->loadByCustomerRule($customerId, $ruleId);
-            if ($ruleCustomer->getId()) {
-                if ($ruleCustomer->getTimesUsed() >= $rule->getUsesPerCustomer()) {
-                    $rule->setIsValidForAddress($address, false);
-                    return false;
-                }
-            }
-        }
-        $rule->afterLoad();
-        /**
-         * quote does not meet rule's conditions
-         */
-        if (!$rule->validate($address)) {
-            $rule->setIsValidForAddress($address, false);
-            return false;
-        }
-        /**
-         * passed all validations, remember to be valid
-         */
-        $rule->setIsValidForAddress($address, true);
-        return true;
-    }
-
     /**
      * Set skip actions validation flag
      *
@@ -290,7 +181,7 @@ class Validator extends \Magento\Framework\Model\AbstractModel
     {
         $address = $item->getAddress();
         foreach ($this->_getRules() as $rule) {
-            if (!$this->_canProcessRule($rule, $address) || !$rule->getActions()->validate($item)) {
+            if (!$this->validatorUtility->canProcessRule($rule, $address) || !$rule->getActions()->validate($item)) {
                 return false;
             }
         }
@@ -332,8 +223,13 @@ class Validator extends \Magento\Framework\Model\AbstractModel
             return $this;
         }
 
-        $appliedRuleIds = $this->applyRules($item);
-        $this->setAppliedRuleIds($item, $appliedRuleIds);
+        $appliedRuleIds = $this->rulesApplier->applyRules(
+            $item,
+            $this->_getRules(),
+            $this->_skipActionsValidation,
+            $this->getCouponCode()
+        );
+        $this->rulesApplier->setAppliedRuleIds($item, $appliedRuleIds);
 
         return $this;
     }
@@ -367,11 +263,11 @@ class Validator extends \Magento\Framework\Model\AbstractModel
             switch ($rule->getSimpleAction()) {
                 case \Magento\SalesRule\Model\Rule::TO_PERCENT_ACTION:
                     $rulePercent = max(0, 100 - $rule->getDiscountAmount());
-                    // break is intentionally omitted
+                // break is intentionally omitted
                 case \Magento\SalesRule\Model\Rule::BY_PERCENT_ACTION:
                     $discountAmount = ($shippingAmount - $address->getShippingDiscountAmount()) * $rulePercent / 100;
                     $baseDiscountAmount = ($baseShippingAmount -
-                        $address->getBaseShippingDiscountAmount()) * $rulePercent / 100;
+                            $address->getBaseShippingDiscountAmount()) * $rulePercent / 100;
                     $discountPercent = min(100, $address->getShippingDiscountPercent() + $rulePercent);
                     $address->setShippingDiscountPercent($discountPercent);
                     break;
@@ -413,42 +309,19 @@ class Validator extends \Magento\Framework\Model\AbstractModel
             $address->setBaseShippingDiscountAmount($baseDiscountAmount);
             $appliedRuleIds[$rule->getRuleId()] = $rule->getRuleId();
 
-            $this->_maintainAddressCouponCode($address, $rule);
-            $this->_addDiscountDescription($address, $rule);
+            $this->rulesApplier->maintainAddressCouponCode($address, $rule, $this->getCouponCode());
+            $this->rulesApplier->addDiscountDescription($address, $rule);
             if ($rule->getStopRulesProcessing()) {
                 break;
             }
         }
 
-        $address->setAppliedRuleIds($this->mergeIds($address->getAppliedRuleIds(), $appliedRuleIds));
-        $quote->setAppliedRuleIds($this->mergeIds($quote->getAppliedRuleIds(), $appliedRuleIds));
+        $address->setAppliedRuleIds($this->validatorUtility->mergeIds($address->getAppliedRuleIds(), $appliedRuleIds));
+        $quote->setAppliedRuleIds($this->validatorUtility->mergeIds($quote->getAppliedRuleIds(), $appliedRuleIds));
 
         return $this;
     }
 
-    /**
-     * Merge two sets of ids
-     *
-     * @param array|string $a1
-     * @param array|string $a2
-     * @param bool $asString
-     * @return array
-     */
-    public function mergeIds($a1, $a2, $asString = true)
-    {
-        if (!is_array($a1)) {
-            $a1 = empty($a1) ? array() : explode(',', $a1);
-        }
-        if (!is_array($a2)) {
-            $a2 = empty($a2) ? array() : explode(',', $a2);
-        }
-        $a = array_unique(array_merge($a1, $a2));
-        if ($asString) {
-            $a = implode(',', $a);
-        }
-        return $a;
-    }
-
     /**
      * Calculate quote totals for each rule and save results
      *
@@ -465,12 +338,9 @@ class Validator extends \Magento\Framework\Model\AbstractModel
         }
 
         foreach ($this->_getRules() as $rule) {
-            if (\Magento\SalesRule\Model\Rule::CART_FIXED_ACTION == $rule->getSimpleAction() && $this->_canProcessRule(
-                $rule,
-                $address
-            )
+            if (\Magento\SalesRule\Model\Rule::CART_FIXED_ACTION == $rule->getSimpleAction()
+                && $this->validatorUtility->canProcessRule($rule, $address)
             ) {
-
                 $ruleTotalItemsPrice = 0;
                 $ruleTotalBaseItemsPrice = 0;
                 $validItemsCount = 0;
@@ -483,7 +353,7 @@ class Validator extends \Magento\Framework\Model\AbstractModel
                     if (!$rule->getActions()->validate($item)) {
                         continue;
                     }
-                    $qty = $this->_getItemQty($item, $rule);
+                    $qty = $this->validatorUtility->getItemQty($item, $rule);
                     $ruleTotalItemsPrice += $this->getItemPrice($item) * $qty;
                     $ruleTotalBaseItemsPrice += $this->getItemBasePrice($item) * $qty;
                     $validItemsCount++;
@@ -497,54 +367,6 @@ class Validator extends \Magento\Framework\Model\AbstractModel
             }
         }
 
-        $this->_stopFurtherRules = false;
-        return $this;
-    }
-
-    /**
-     * Set coupon code to address if $rule contains validated coupon
-     *
-     * @param Address $address
-     * @param \Magento\SalesRule\Model\Rule $rule
-     * @return $this
-     */
-    protected function _maintainAddressCouponCode($address, $rule)
-    {
-        /*
-        Rule is a part of rules collection, which includes only rules with 'No Coupon' type or with validated coupon.
-        As a result, if rule uses coupon code(s) ('Specific' or 'Auto' Coupon Type), it always contains validated coupon
-        */
-        if ($rule->getCouponType() != \Magento\SalesRule\Model\Rule::COUPON_TYPE_NO_COUPON) {
-            $address->setCouponCode($this->getCouponCode());
-        }
-
-        return $this;
-    }
-
-    /**
-     * Add rule discount description label to address object
-     *
-     * @param Address $address
-     * @param \Magento\SalesRule\Model\Rule $rule
-     * @return $this
-     */
-    protected function _addDiscountDescription($address, $rule)
-    {
-        $description = $address->getDiscountDescriptionArray();
-        $ruleLabel = $rule->getStoreLabel($address->getQuote()->getStore());
-        $label = '';
-        if ($ruleLabel) {
-            $label = $ruleLabel;
-        } else if (strlen($address->getCouponCode())) {
-            $label = $address->getCouponCode();
-        }
-
-        if (strlen($label)) {
-            $description[$rule->getId()] = $label;
-        }
-
-        $address->setDiscountDescriptionArray($description);
-
         return $this;
     }
 
@@ -595,20 +417,6 @@ class Validator extends \Magento\Framework\Model\AbstractModel
         return $this->_taxData->getPrice($item, $item->getBaseOriginalPrice(), true);
     }
 
-    /**
-     * Return discount item qty
-     *
-     * @param AbstractItem $item
-     * @param \Magento\SalesRule\Model\Rule $rule
-     * @return int
-     */
-    protected function _getItemQty($item, $rule)
-    {
-        $qty = $item->getTotalQty();
-        $discountQty = $rule->getDiscountQty();
-        return $discountQty ? min($qty, $discountQty) : $qty;
-    }
-
     /**
      * Convert address discount description array to string
      *
@@ -660,115 +468,6 @@ class Validator extends \Magento\Framework\Model\AbstractModel
         return $items;
     }
 
-    /**
-     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
-     * @param int[] $appliedRuleIds
-     * @return $this
-     */
-    protected function setAppliedRuleIds(\Magento\Sales\Model\Quote\Item\AbstractItem $item, array $appliedRuleIds)
-    {
-        $address = $item->getAddress();
-        $quote = $item->getQuote();
-
-        $item->setAppliedRuleIds(join(',', $appliedRuleIds));
-        $address->setAppliedRuleIds($this->mergeIds($address->getAppliedRuleIds(), $appliedRuleIds));
-        $quote->setAppliedRuleIds($this->mergeIds($quote->getAppliedRuleIds(), $appliedRuleIds));
-
-        return $this;
-    }
-
-    /**
-     * Fire event to allow overwriting of discount amounts
-     *
-     * @param \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData
-     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
-     * @param \Magento\SalesRule\Model\Rule $rule
-     * @param float $qty
-     * @return $this
-     */
-    protected function eventFix(
-        \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData,
-        \Magento\Sales\Model\Quote\Item\AbstractItem $item,
-        \Magento\SalesRule\Model\Rule $rule,
-        $qty
-    ) {
-        $quote = $item->getQuote();
-        $address = $item->getAddress();
-
-        $this->_eventManager->dispatch(
-            'salesrule_validator_process',
-            array(
-                'rule' => $rule,
-                'item' => $item,
-                'address' => $address,
-                'quote' => $quote,
-                'qty' => $qty,
-                'result' => $discountData
-            )
-        );
-
-        return $this;
-    }
-
-    /**
-     * Process "delta" rounding
-     *
-     * @param \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData
-     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
-     * @return $this
-     */
-    protected function deltaRoundingFix(
-        \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData,
-        \Magento\Sales\Model\Quote\Item\AbstractItem $item
-    ) {
-        $store = $item->getQuote()->getStore();
-        $discountAmount = $discountData->getAmount();
-        $baseDiscountAmount = $discountData->getBaseAmount();
-
-        //TODO Seems \Magento\Sales\Model\Quote\Item\AbstractItem::getDiscountPercent() returns float value
-        //that can not be used as array index
-        $percentKey = $item->getDiscountPercent();
-        if ($percentKey) {
-            $delta = isset($this->_roundingDeltas[$percentKey]) ? $this->_roundingDeltas[$percentKey] : 0;
-            $baseDelta = isset($this->_baseRoundingDeltas[$percentKey]) ? $this->_baseRoundingDeltas[$percentKey] : 0;
-
-            $discountAmount += $delta;
-            $baseDiscountAmount += $baseDelta;
-
-            $this->_roundingDeltas[$percentKey] = $discountAmount - $store->roundPrice($discountAmount);
-            $this->_baseRoundingDeltas[$percentKey] = $baseDiscountAmount - $store->roundPrice($baseDiscountAmount);
-        }
-
-        $discountData->setAmount($store->roundPrice($discountAmount));
-        $discountData->setBaseAmount($store->roundPrice($baseDiscountAmount));
-
-        return $this;
-    }
-
-    /**
-     * @param Rule\Action\Discount\Data $discountData
-     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
-     * @param float $qty
-     * @return void
-     */
-    protected function minFix(
-        \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData,
-        \Magento\Sales\Model\Quote\Item\AbstractItem $item,
-        $qty
-    ) {
-        $itemPrice = $this->getItemPrice($item);
-        $baseItemPrice = $this->getItemBasePrice($item);
-
-        $itemDiscountAmount = $item->getDiscountAmount();
-        $itemBaseDiscountAmount = $item->getBaseDiscountAmount();
-
-        $discountAmount = min($itemDiscountAmount + $discountData->getAmount(), $itemPrice * $qty);
-        $baseDiscountAmount = min($itemBaseDiscountAmount + $discountData->getBaseAmount(), $baseItemPrice * $qty);
-
-        $discountData->setAmount($discountAmount);
-        $discountData->setBaseAmount($baseDiscountAmount);
-    }
-
     /**
      * @param int $key
      * @return array
@@ -793,97 +492,4 @@ class Validator extends \Magento\Framework\Model\AbstractModel
 
         return $this;
     }
-
-    /**
-     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
-     * @return array
-     */
-    protected function applyRules($item)
-    {
-        $address = $item->getAddress();
-
-        $appliedRuleIds = array();
-        /* @var $rule \Magento\SalesRule\Model\Rule */
-        foreach ($this->_getRules() as $rule) {
-            if ($this->_stopFurtherRules) {
-                break;
-            }
-
-            if (!$this->_canProcessRule($rule, $address)) {
-                continue;
-            }
-
-            if (!$this->_skipActionsValidation && !$rule->getActions()->validate($item)) {
-                continue;
-            }
-
-            $this->applyRule($item, $rule, $address);
-            $appliedRuleIds[$rule->getRuleId()] = $rule->getRuleId();
-
-            if ($rule->getStopRulesProcessing()) {
-                $this->_stopFurtherRules = true;
-                break;
-            }
-        }
-
-        return $appliedRuleIds;
-    }
-
-    /**
-     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
-     * @param \Magento\SalesRule\Model\Rule $rule
-     * @param \Magento\Sales\Model\Quote\Address $address
-     * @return $this
-     */
-    protected function applyRule($item, $rule, $address)
-    {
-        $discountData = $this->getDiscountData($item, $rule);
-        $this->setDiscountData($discountData, $item);
-
-        $this->_maintainAddressCouponCode($address, $rule);
-        $this->_addDiscountDescription($address, $rule);
-
-        return $this;
-    }
-
-    /**
-     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
-     * @param \Magento\SalesRule\Model\Rule $rule
-     * @return Rule\Action\Discount\Data
-     */
-    protected function getDiscountData($item, $rule)
-    {
-        $qty = $this->_getItemQty($item, $rule);
-
-        $discountCalculator = $this->calculatorFactory->create($rule->getSimpleAction());
-        $qty = $discountCalculator->fixQuantity($qty, $rule);
-        $discountData = $discountCalculator->calculate($rule, $item, $qty);
-
-        $this->eventFix($discountData, $item, $rule, $qty);
-        $this->deltaRoundingFix($discountData, $item);
-
-        /**
-         * We can't use row total here because row total not include tax
-         * Discount can be applied on price included tax
-         */
-
-        $this->minFix($discountData, $item, $qty);
-
-        return $discountData;
-    }
-
-    /**
-     * @param Rule\Action\Discount\Data $discountData
-     * @param \Magento\Sales\Model\Quote\Item\AbstractItem $item
-     * @return $this
-     */
-    protected function setDiscountData($discountData, $item)
-    {
-        $item->setDiscountAmount($discountData->getAmount());
-        $item->setBaseDiscountAmount($discountData->getBaseAmount());
-        $item->setOriginalDiscountAmount($discountData->getOriginalAmount());
-        $item->setBaseOriginalDiscountAmount($discountData->getBaseOriginalAmount());
-
-        return $this;
-    }
 }
diff --git a/app/code/Magento/Sendfriend/view/frontend/templates/send.phtml b/app/code/Magento/Sendfriend/view/frontend/templates/send.phtml
index 275153630f44c2640d404923ace593da5f747c68..911cf5fe89d2005e59621d1276baf038e6cd37b6 100644
--- a/app/code/Magento/Sendfriend/view/frontend/templates/send.phtml
+++ b/app/code/Magento/Sendfriend/view/frontend/templates/send.phtml
@@ -31,7 +31,7 @@
     <div class="actions-toolbar">
         <div class="secondary">
             <button type="button" id="btn-remove${_index_}" class="action remove"
-               title="<?php echo $this->escapeJsQuote(__('Remove Email')) ?>"><span><?php echo $this->escapeJsQuote(__('Remove Email')) ?></span></button>
+               title="<?php echo $this->escapeJsQuote(__('Remove')) ?>"><span><?php echo $this->escapeJsQuote(__('Remove')) ?></span></button>
         </div>
     </div>
     <fieldset class="fieldset">
diff --git a/app/code/Magento/Shipping/view/frontend/layout/sales_order_shipment.xml b/app/code/Magento/Shipping/view/frontend/layout/sales_order_shipment.xml
index 753d3a45406a1a1c60480cca8a06454217c143f7..93e203f6427964dba79f246ec4d414c1099499d6 100644
--- a/app/code/Magento/Shipping/view/frontend/layout/sales_order_shipment.xml
+++ b/app/code/Magento/Shipping/view/frontend/layout/sales_order_shipment.xml
@@ -26,7 +26,7 @@
 <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Core/etc/layout_single.xsd">
     <update handle="sales_order_shipment_renderers" />
     <referenceContainer name="content">
-        <block class="Magento\Shipping\Block\Order\Shipment" name="sales.order.shipment" after="sales.order.info" cacheable="false">
+        <block class="Magento\Shipping\Block\Order\Shipment" name="sales.order.shipment" cacheable="false">
             <block class="Magento\Shipping\Block\Items" name="shipment_items" template="items.phtml">
                 <block class="Magento\Framework\View\Element\RendererList" name="sales.order.shipment.renderers" as="renderer.list" />
                 <block class="Magento\Shipping\Block\Tracking\Link" name="track-all-link" template="tracking/link.phtml">
diff --git a/app/code/Magento/Shipping/view/frontend/templates/items.phtml b/app/code/Magento/Shipping/view/frontend/templates/items.phtml
index ce25944c50aa294e54fa7e27794078ba81f4b87b..55f3d5187a9d55a7ff5ed6eef85e5500b3c9ba50 100644
--- a/app/code/Magento/Shipping/view/frontend/templates/items.phtml
+++ b/app/code/Magento/Shipping/view/frontend/templates/items.phtml
@@ -24,20 +24,18 @@
 ?>
 <?php /** @var  $this \Magento\Shipping\Block\Items */ ?>
 <?php  $_order = $this->getOrder() ?>
-<div class="order toolbar">
-    <div class="actions">
-        <?php  if ($_order->getTracksCollection()->count()) : ?>
-            <?php echo $this->getChildHtml('track-all-link') ?>
-        <?php endif; ?>
-        <a href="<?php echo $this->getPrintAllShipmentsUrl($_order) ?>"
-           onclick="this.target='_blank'"
-           class="action print">
-            <span><?php echo __('Print All Shipments') ?></span>
-        </a>
-    </div>
+<div class="actions-toolbar">
+    <?php if ($_order->getTracksCollection()->count()) : ?>
+        <?php echo $this->getChildHtml('track-all-link') ?>
+    <?php endif; ?>
+    <a href="<?php echo $this->getPrintAllShipmentsUrl($_order) ?>"
+       onclick="this.target='_blank'"
+       class="action print">
+        <span><?php echo __('Print All Shipments') ?></span>
+    </a>
 </div>
 <?php foreach ($_order->getShipmentsCollection() as $_shipment): ?>
-<div class="order title">
+<div class="order-title">
     <strong><?php echo __('Shipment #') ?><?php echo $_shipment->getIncrementId(); ?></strong>
     <a href="<?php echo $this->getPrintShipmentUrl($_shipment) ?>"
        onclick="this.target='_blank'"
@@ -53,35 +51,27 @@
 </div>
 <?php $tracks = $_shipment->getTracksCollection(); ?>
 <?php  if ($tracks->count()): ?>
-    <table class="data table order tracking" id="my-tracking-table-<?php echo $_shipment->getId(); ?>">
-        <tbody>
-            <tr>
-                <th class="col label"><?php echo __('Tracking Number(s):') ?></th>
-                <td class="col number">
-                <?php
-                $i = 1;
-                $_size = $tracks->count();
-                foreach($tracks as $track): ?>
-                <?php if($track->isCustom()): ?>
-                    <?php echo $this->escapeHtml($track->getNumber()) ?>
-                <?php else: ?>
-                    <a href="#"
-                       data-mage-init='{"popupWindow": {"windowURL":"<?php echo $this->helper('Magento\Shipping\Helper\Data')->getTrackingPopupUrlBySalesModel($track) ?>","windowName":"trackorder","width":800,"height":600,"left":0,"top":0,"resizable":1,"scrollbars":1}}'
-                       class="action track">
-                        <span><?php echo $this->escapeHtml($track->getNumber()) ?></span>
-                    </a>
-                <?php endif; ?>
-                <?php if($i!=$_size): ?>, <?php endif; ?>
+    <dl class="order-tracking" id="my-tracking-table-<?php echo $_shipment->getId(); ?>">
+        <dt class="tracking-title">
+            <?php echo __('Tracking Number(s):') ?>
+        </dt>
+        <dd class="tracking-content">
+            <?php
+            $i = 1;
+            $_size = $tracks->count();
+            foreach ($tracks as $track): ?>
+                <?php if ($track->isCustom()): ?><?php echo $this->escapeHtml($track->getNumber()) ?><?php else: ?><a
+                    href="#"
+                    data-mage-init='{"popupWindow": {"windowURL":"<?php echo $this->helper('Magento\Shipping\Helper\Data')->getTrackingPopupUrlBySalesModel($track) ?>","windowName":"trackorder","width":800,"height":600,"left":0,"top":0,"resizable":1,"scrollbars":1}}'
+                    class="action track"><span><?php echo $this->escapeHtml($track->getNumber()) ?></span>
+                    </a><?php endif; ?><?php if ($i != $_size): ?>, <?php endif; ?>
                 <?php $i++;
-                endforeach; ?>
-                </td>
-            </tr>
-        </tbody>
-    </table>
+            endforeach; ?>
+        </dd>
+    </dl>
 <?php  endif; ?>
-<div class="order subtitle caption"><strong><?php echo __('Items Shipped') ?></strong></div>
-<div class="wrapper table order items shipment">
-    <table class="data table order items shipment" id="my-shipment-table-<?php echo $_shipment->getId(); ?>">
+<div class="table-wrapper order-items-shipment">
+    <table class="data table table-order-items shipment" id="my-shipment-table-<?php echo $_shipment->getId(); ?>">
         <caption class="table caption"><?php echo __('Items Shipped') ?></caption>
         <thead>
             <tr>
diff --git a/app/code/Magento/Shipping/view/frontend/templates/order/shipment.phtml b/app/code/Magento/Shipping/view/frontend/templates/order/shipment.phtml
index 89362b4377019522faedf4617ae0c63d4dbca208..e019f5067eab3f3bde1473bab8efd5ef6545a20e 100644
--- a/app/code/Magento/Shipping/view/frontend/templates/order/shipment.phtml
+++ b/app/code/Magento/Shipping/view/frontend/templates/order/shipment.phtml
@@ -22,7 +22,7 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 ?>
-<div class="order items details shipments">
+<div class="order-details-items shipments">
     <?php echo $this->getChildHtml('shipment_items') ?>
     <div class="actions-toolbar">
         <div class="secondary">
diff --git a/app/code/Magento/Tax/Helper/Data.php b/app/code/Magento/Tax/Helper/Data.php
index 76569e00913619cdead2f0b6dc4cdf3521d57ddb..c87caae9d81af6efb9de5a7100e8b88d71eb16cc 100644
--- a/app/code/Magento/Tax/Helper/Data.php
+++ b/app/code/Magento/Tax/Helper/Data.php
@@ -28,6 +28,8 @@ use Magento\Customer\Model\Address;
 use Magento\Tax\Model\Config;
 use Magento\Tax\Service\V1\Data\QuoteDetailsBuilder;
 use Magento\Tax\Service\V1\Data\QuoteDetails\ItemBuilder as QuoteDetailsItemBuilder;
+use Magento\Tax\Service\V1\Data\TaxClassKey;
+use Magento\Tax\Service\V1\Data\TaxClassKeyBuilder;
 use Magento\Tax\Service\V1\TaxCalculationServiceInterface;
 use Magento\Customer\Model\Address\Converter as AddressConverter;
 
@@ -149,6 +151,13 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
      */
     protected $addressConverter;
 
+    /**
+     * TaxClassKey builder
+     *
+     * @var TaxClassKeyBuilder
+     */
+    protected $taxClassKeyBuilder;
+
     /**
      * @param \Magento\Framework\App\Helper\Context $context
      * @param \Magento\Core\Helper\Data $coreData
@@ -163,6 +172,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
      * @param \Magento\Framework\Locale\ResolverInterface $localeResolver
      * @param QuoteDetailsBuilder $quoteDetailsBuilder
      * @param QuoteDetailsItemBuilder $quoteDetailsItemBuilder
+     * @param TaxClassKeyBuilder $taxClassKeyBuilder
      * @param TaxCalculationServiceInterface $taxCalculationService
      * @param AddressConverter $addressConverter
      */
@@ -180,6 +190,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
         \Magento\Framework\Locale\ResolverInterface $localeResolver,
         QuoteDetailsBuilder $quoteDetailsBuilder,
         QuoteDetailsItemBuilder $quoteDetailsItemBuilder,
+        TaxClassKeyBuilder $taxClassKeyBuilder,
         TaxCalculationServiceInterface $taxCalculationService,
         AddressConverter $addressConverter
     ) {
@@ -196,6 +207,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
         $this->_localeResolver = $localeResolver;
         $this->quoteDetailsBuilder = $quoteDetailsBuilder;
         $this->quoteDetailsItemBuilder = $quoteDetailsItemBuilder;
+        $this->taxClassKeyBuilder = $taxClassKeyBuilder;
         $this->taxCalculationService = $taxCalculationService;
         $this->addressConverter = $addressConverter;
     }
@@ -570,16 +582,20 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
             $item = $this->quoteDetailsItemBuilder->setQuantity(1)
                 ->setCode($product->getSku())
                 ->setShortDescription($product->getShortDescription())
-                ->setTaxClassId($product->getTaxClassId())
-                ->setTaxIncluded($priceIncludesTax)
+                ->setTaxClassKey(
+                    $this->taxClassKeyBuilder->setType(TaxClassKey::TYPE_ID)
+                        ->setValue($product->getTaxClassId())->create()
+                )->setTaxIncluded($priceIncludesTax)
                 ->setType('product')
                 ->setUnitPrice($price)
                 ->create();
             $quoteDetails = $this->quoteDetailsBuilder
                 ->setShippingAddress($shippingAddressDataObject)
                 ->setBillingAddress($billingAddressDataObject)
-                ->setCustomerTaxClassId($ctc)
-                ->setItems([$item])
+                ->setCustomerTaxClassKey(
+                    $this->taxClassKeyBuilder->setType(TaxClassKey::TYPE_ID)
+                        ->setValue($ctc)->create()
+                )->setItems([$item])
                 ->create();
 
             $storeId = null;
diff --git a/app/code/Magento/Tax/Model/Calculation.php b/app/code/Magento/Tax/Model/Calculation.php
index ab4fddc830125d79760597c6d8da93d13f248835..52e592ec26f74072539edd2c89d9138236151605 100644
--- a/app/code/Magento/Tax/Model/Calculation.php
+++ b/app/code/Magento/Tax/Model/Calculation.php
@@ -552,13 +552,15 @@ class Calculation extends \Magento\Framework\Model\AbstractModel
                 break;
         }
 
-        if (is_null($customerTaxClass) && $customerId) {
-            $customerData = $this->customerAccountService->getCustomer($customerId);
-            $customerTaxClass = $this->_groupService->getGroup($customerData->getGroupId())->getTaxClassId();
-        } elseif ($customerTaxClass === false && !$customerId) {
-            $customerTaxClass = $this->_groupService
-                ->getGroup(GroupServiceInterface::NOT_LOGGED_IN_ID)
-                ->getTaxClassId();
+        if (is_null($customerTaxClass) || $customerTaxClass === false) {
+            if ($customerId) {
+                $customerData = $this->customerAccountService->getCustomer($customerId);
+                $customerTaxClass = $this->_groupService->getGroup($customerData->getGroupId())->getTaxClassId();
+            } else {
+                $customerTaxClass = $this->_groupService->getGroup(
+                    GroupServiceInterface::NOT_LOGGED_IN_ID
+                )->getTaxClassId();
+            }
         }
 
         $request = new \Magento\Framework\Object();
@@ -639,49 +641,6 @@ class Calculation extends \Magento\Framework\Model\AbstractModel
         return $identical;
     }
 
-    /**
-     * Gets the tax rates by type
-     *
-     * @param \Magento\Framework\Object $request
-     * @param string|array $fieldName
-     * @param string|array $type
-     * @return array
-     */
-    protected function _getRates($request, $fieldName, $type)
-    {
-        $result = array();
-        /** @var $classes \Magento\Tax\Model\Resource\TaxClass\Collection */
-        $classes = $this->_classesFactory->create();
-        $classes->addFieldToFilter('class_type', $type)->load();
-        foreach ($classes as $class) {
-            $request->setData($fieldName, $class->getId());
-            $result[$class->getId()] = $this->getRate($request);
-        }
-        return $result;
-    }
-
-    /**
-     * Gets rates for all the product tax classes
-     *
-     * @param \Magento\Framework\Object $request
-     * @return array
-     */
-    public function getRatesForAllProductTaxClasses($request)
-    {
-        return $this->_getRates($request, 'product_class_id', \Magento\Tax\Model\ClassModel::TAX_CLASS_TYPE_PRODUCT);
-    }
-
-    /**
-     * Gets rates for all the customer tax classes
-     *
-     * @param \Magento\Framework\Object $request
-     * @return array
-     */
-    public function getRatesForAllCustomerTaxClasses($request)
-    {
-        return $this->_getRates($request, 'customer_class_id', \Magento\Tax\Model\ClassModel::TAX_CLASS_TYPE_CUSTOMER);
-    }
-
     /**
      * Get information about tax rates applied to request
      *
diff --git a/app/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php b/app/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php
new file mode 100644
index 0000000000000000000000000000000000000000..ecfbc2ef49f03161672373391ed7475c0b824f23
--- /dev/null
+++ b/app/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php
@@ -0,0 +1,187 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Model\Calculation;
+
+use Magento\Tax\Model\Calculation;
+use Magento\Customer\Service\V1\Data\Address;
+use Magento\Tax\Service\V1\Data\QuoteDetails\Item as QuoteDetailsItem;
+
+abstract class AbstractAggregateCalculator extends AbstractCalculator
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function calculateWithTaxInPrice(QuoteDetailsItem $item, $quantity)
+    {
+        $taxRateRequest = $this->getAddressRateRequest()->setProductClassId(
+            $this->taxClassService->getTaxClassId($item->getTaxClassKey())
+        );
+        $rate = $this->calculationTool->getRate($taxRateRequest);
+        $storeRate = $storeRate = $this->calculationTool->getStoreRate($taxRateRequest, $this->storeId);
+
+        // Calculate $rowTotalInclTax
+        $priceInclTax = $this->calculationTool->round($item->getUnitPrice());
+        $rowTotalInclTax = $priceInclTax * $quantity;
+        if (!$this->isSameRateAsStore($rate, $storeRate)) {
+            $priceInclTax = $this->calculatePriceInclTax($priceInclTax, $storeRate, $rate);
+            $rowTotalInclTax = $priceInclTax * $quantity;
+        }
+        $rowTaxExact = $this->calculationTool->calcTaxAmount($rowTotalInclTax, $rate, true, false);
+        $rowTax = $this->roundAmount($rowTaxExact, $rate, true);
+        $rowTotal = $rowTotalInclTax - $rowTax;
+        $price = $this->calculationTool->round($rowTotal / $quantity);
+
+        //Handle discount
+        $discountTaxCompensationAmount = 0;
+        $applyTaxAfterDiscount = $this->config->applyTaxAfterDiscount($this->storeId);
+        $discountAmount = $item->getDiscountAmount();
+        if ($discountAmount && $applyTaxAfterDiscount) {
+            //TODO: handle originalDiscountAmount
+            $taxableAmount = max($rowTotalInclTax - $discountAmount, 0);
+            $rowTaxAfterDiscount = $this->calculationTool->calcTaxAmount(
+                $taxableAmount,
+                $rate,
+                true,
+                false
+            );
+            $rowTaxAfterDiscount = $this->roundAmount(
+                $rowTaxAfterDiscount,
+                $rate,
+                true,
+                self::KEY_TAX_AFTER_DISCOUNT_DELTA_ROUNDING
+            );
+            // Set discount tax compensation
+            $discountTaxCompensationAmount = $rowTax - $rowTaxAfterDiscount;
+            $rowTax = $rowTaxAfterDiscount;
+        }
+
+        // Calculate applied taxes
+        /** @var  \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[] $appliedTaxes */
+        $appliedTaxes = [];
+        $appliedRates = $this->calculationTool->getAppliedRates($taxRateRequest);
+        $appliedTaxes = $this->getAppliedTaxes($rowTax, $rate, $appliedRates);
+
+        $this->taxDetailsItemBuilder->setCode($item->getCode());
+        $this->taxDetailsItemBuilder->setType($item->getType());
+        $this->taxDetailsItemBuilder->setRowTax($rowTax);
+        $this->taxDetailsItemBuilder->setPrice($price);
+        $this->taxDetailsItemBuilder->setPriceInclTax($priceInclTax);
+        $this->taxDetailsItemBuilder->setRowTotal($rowTotal);
+        $this->taxDetailsItemBuilder->setRowTotalInclTax($rowTotalInclTax);
+        $this->taxDetailsItemBuilder->setDiscountTaxCompensationAmount($discountTaxCompensationAmount);
+        $this->taxDetailsItemBuilder->setAssociatedItemCode($item->getAssociatedItemCode());
+        $this->taxDetailsItemBuilder->setTaxPercent($rate);
+        $this->taxDetailsItemBuilder->setAppliedTaxes($appliedTaxes);
+        return $this->taxDetailsItemBuilder->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function calculateWithTaxNotInPrice(QuoteDetailsItem $item, $quantity)
+    {
+        $taxRateRequest = $this->getAddressRateRequest()->setProductClassId(
+            $this->taxClassService->getTaxClassId($item->getTaxClassKey())
+        );
+        $rate = $this->calculationTool->getRate($taxRateRequest);
+        $appliedRates = $this->calculationTool->getAppliedRates($taxRateRequest);
+
+        $applyTaxAfterDiscount = $this->config->applyTaxAfterDiscount($this->storeId);
+        $discountAmount = $item->getDiscountAmount();
+        $discountTaxCompensationAmount = 0;
+
+        // Calculate $rowTotal
+        $price = $this->calculationTool->round($item->getUnitPrice());
+        $rowTotal = $price * $quantity;
+        $rowTaxes = [];
+        $rowTaxesBeforeDiscount = [];
+        $appliedTaxes = [];
+        //Apply each tax rate separately
+        foreach ($appliedRates as $appliedRate) {
+            $taxId = $appliedRate['id'];
+            $taxRate = $appliedRate['percent'];
+            $rowTaxPerRate = $this->calculationTool->calcTaxAmount($rowTotal, $taxRate, false, false);
+            $rowTaxPerRate = $this->roundAmount($rowTaxPerRate, $taxRate, false);
+            $rowTaxAfterDiscount = $rowTaxPerRate;
+
+            //Handle discount
+            if ($discountAmount && $applyTaxAfterDiscount) {
+                //TODO: handle originalDiscountAmount
+                $taxableAmount = max($rowTotal - $discountAmount, 0);
+                $rowTaxAfterDiscount = $this->calculationTool->calcTaxAmount(
+                    $taxableAmount,
+                    $taxRate,
+                    false,
+                    false
+                );
+                $rowTaxAfterDiscount = $this->roundAmount(
+                    $rowTaxAfterDiscount,
+                    $taxRate,
+                    false,
+                    self::KEY_TAX_AFTER_DISCOUNT_DELTA_ROUNDING
+                );
+            }
+            $appliedTaxes[$taxId] = $this->getAppliedTax(
+                $rowTaxAfterDiscount,
+                $appliedRate
+            );
+
+            $rowTaxes[] = $rowTaxAfterDiscount;
+            $rowTaxesBeforeDiscount[] = $rowTaxPerRate;
+        }
+        $rowTax = array_sum($rowTaxes);
+        $rowTaxBeforeDiscount = array_sum($rowTaxesBeforeDiscount);
+        $rowTotalInclTax = $rowTotal + $rowTaxBeforeDiscount;
+        $priceInclTax = $this->calculationTool->round($rowTotalInclTax / $quantity);
+
+        $this->taxDetailsItemBuilder->setCode($item->getCode());
+        $this->taxDetailsItemBuilder->setType($item->getType());
+        $this->taxDetailsItemBuilder->setRowTax($rowTax);
+        $this->taxDetailsItemBuilder->setPrice($price);
+        $this->taxDetailsItemBuilder->setPriceInclTax($priceInclTax);
+        $this->taxDetailsItemBuilder->setRowTotal($rowTotal);
+        $this->taxDetailsItemBuilder->setRowTotalInclTax($rowTotalInclTax);
+        $this->taxDetailsItemBuilder->setDiscountTaxCompensationAmount($discountTaxCompensationAmount);
+        $this->taxDetailsItemBuilder->setAssociatedItemCode($item->getAssociatedItemCode());
+        $this->taxDetailsItemBuilder->setTaxPercent($rate);
+        $this->taxDetailsItemBuilder->setAppliedTaxes($appliedTaxes);
+        return $this->taxDetailsItemBuilder->create();
+    }
+
+    /**
+     * Round amount
+     *
+     * @param float $amount
+     * @param null|float $rate
+     * @param null|bool $direction
+     * @param string $type
+     * @return float
+     */
+    abstract protected function roundAmount(
+        $amount,
+        $rate = null,
+        $direction = null,
+        $type = self::KEY_REGULAR_DELTA_ROUNDING
+    );
+}
diff --git a/app/code/Magento/Tax/Model/Calculation/AbstractCalculator.php b/app/code/Magento/Tax/Model/Calculation/AbstractCalculator.php
new file mode 100644
index 0000000000000000000000000000000000000000..922bdd04cee45c47dce9e9913b455cfb20ec43fd
--- /dev/null
+++ b/app/code/Magento/Tax/Model/Calculation/AbstractCalculator.php
@@ -0,0 +1,441 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Model\Calculation;
+
+use Magento\Tax\Model\Calculation;
+use Magento\Customer\Service\V1\Data\Address;
+use Magento\Tax\Service\V1\Data\QuoteDetails\Item as QuoteDetailsItem;
+use Magento\Tax\Service\V1\Data\QuoteDetails;
+use Magento\Tax\Service\V1\Data\TaxDetails\ItemBuilder as TaxDetailsItemBuilder;
+use Magento\Tax\Service\V1\Data\TaxDetails\Item as TaxDetailsItem;
+use Magento\Tax\Service\V1\Data\TaxClassKey;
+use \Magento\Tax\Service\V1\Data\TaxClass;
+use Magento\Tax\Service\V1\TaxClassService;
+
+abstract class AbstractCalculator
+{
+    /**#@+
+     * Constants for delta rounding key
+     */
+    const KEY_REGULAR_DELTA_ROUNDING = 'regular';
+
+    const KEY_APPLIED_TAX_DELTA_ROUNDING = 'applied_tax_amount';
+
+    const KEY_TAX_AFTER_DISCOUNT_DELTA_ROUNDING = 'tax_after_discount';
+    /**#@-*/
+
+    /**
+     * Tax details item builder
+     *
+     * @var TaxDetailsItemBuilder
+     */
+    protected $taxDetailsItemBuilder;
+
+    /**
+     * Tax calculation tool
+     *
+     * @var Calculation
+     */
+    protected $calculationTool;
+
+    /**
+     * Store id
+     *
+     * @var int
+     */
+    protected $storeId;
+
+    /**
+     * Customer tax class id
+     *
+     * @var int
+     */
+    protected $customerTaxClassId;
+
+    /**
+     * Customer id
+     *
+     * @var int
+     */
+    protected $customerId;
+
+    /**
+     * Shipping Address
+     *
+     * @var Address
+     */
+    protected $shippingAddress;
+
+    /**
+     * Billing Address
+     *
+     * @var Address
+     */
+    protected $billingAddress;
+
+    /**
+     * Tax configuration object
+     *
+     * @var \Magento\Tax\Model\Config
+     */
+    protected $config;
+
+    /**
+     * Address rate request
+     *
+     * Request object contain:
+     *  country_id (->getCountryId())
+     *  region_id (->getRegionId())
+     *  postcode (->getPostcode())
+     *  customer_class_id (->getCustomerClassId())
+     *  store (->getStore())
+     *
+     * @var \Magento\Framework\Object
+     */
+    private $addressRateRequest = null;
+
+    /**
+     * Rounding deltas for prices
+     *
+     * @var string[]
+     * example:
+     *  [
+     *      'type' => [
+     *          'rate' => 'rounding delta',
+     *      ],
+     *  ]
+     */
+    protected $roundingDeltas;
+
+    /**
+     * Tax Class Service
+     *
+     * @var TaxClassService
+     */
+    protected $taxClassService;
+
+    /**
+     * Constructor
+     *
+     * @param TaxClassService $taxClassService
+     * @param TaxDetailsItemBuilder $taxDetailsItemBuilder
+     * @param Calculation $calculationTool
+     * @param \Magento\Tax\Model\Config $config
+     * @param int $storeId
+     * @param \Magento\Framework\Object $addressRateRequest
+     */
+    public function __construct(
+        TaxClassService $taxClassService,
+        TaxDetailsItemBuilder $taxDetailsItemBuilder,
+        Calculation $calculationTool,
+        \Magento\Tax\Model\Config $config,
+        $storeId,
+        \Magento\Framework\Object $addressRateRequest = null
+    ) {
+        $this->taxClassService = $taxClassService;
+        $this->taxDetailsItemBuilder = $taxDetailsItemBuilder;
+        $this->calculationTool = $calculationTool;
+        $this->config = $config;
+        $this->storeId = $storeId;
+        $this->addressRateRequest = $addressRateRequest;
+    }
+
+    /**
+     * Set billing address
+     *
+     * @param Address $billingAddress
+     * @return void
+     */
+    public function setBillingAddress(Address $billingAddress)
+    {
+        $this->billingAddress = $billingAddress;
+    }
+
+    /**
+     * Set shipping address
+     *
+     * @param Address $shippingAddress
+     * @return void
+     */
+    public function setShippingAddress(Address $shippingAddress)
+    {
+        $this->shippingAddress = $shippingAddress;
+    }
+
+    /**
+     * Set customer tax class id
+     *
+     * @param int $customerTaxClassId
+     * @return void
+     */
+    public function setCustomerTaxClassId($customerTaxClassId)
+    {
+        $this->customerTaxClassId = $customerTaxClassId;
+    }
+
+    /**
+     * Set customer id
+     *
+     * @param int $customerId
+     * @return void
+     */
+    public function setCustomerId($customerId)
+    {
+        $this->customerId = $customerId;
+    }
+
+    /**
+     * Calculate tax details for quote item with given quantity
+     *
+     * @param QuoteDetailsItem $item
+     * @param int $quantity
+     * @return TaxDetailsItem
+     */
+    public function calculate(QuoteDetailsItem $item, $quantity)
+    {
+        if ($item->getTaxIncluded()) {
+            return $this->calculateWithTaxInPrice($item, $quantity);
+        } else {
+            return $this->calculateWithTaxNotInPrice($item, $quantity);
+        }
+    }
+
+    /**
+     * Calculate tax details for quote item with tax in price with given quantity
+     *
+     * @param QuoteDetailsItem $item
+     * @param int $quantity
+     * @return TaxDetailsItem
+     */
+    abstract protected function calculateWithTaxInPrice(QuoteDetailsItem $item, $quantity);
+
+    /**
+     * Calculate tax details for quote item with tax not in price with given quantity
+     *
+     * @param QuoteDetailsItem $item
+     * @param int $quantity
+     * @return TaxDetailsItem
+     */
+    abstract protected function calculateWithTaxNotInPrice(QuoteDetailsItem $item, $quantity);
+
+    /**
+     * Get address rate request
+     *
+     * Request object contain:
+     *  country_id (->getCountryId())
+     *  region_id (->getRegionId())
+     *  postcode (->getPostcode())
+     *  customer_class_id (->getCustomerClassId())
+     *  store (->getStore())
+     *
+     * @return \Magento\Framework\Object
+     */
+    protected function getAddressRateRequest()
+    {
+        if (null == $this->addressRateRequest) {
+            $this->addressRateRequest = $this->calculationTool->getRateRequest(
+                $this->shippingAddress,
+                $this->billingAddress,
+                $this->customerTaxClassId,
+                $this->storeId,
+                $this->customerId
+            );
+        }
+        return $this->addressRateRequest;
+    }
+
+    /**
+     * Check if tax rate is same as store tax rate
+     *
+     * @param float $rate
+     * @param float $storeRate
+     * @return bool
+     */
+    protected function isSameRateAsStore($rate, $storeRate)
+    {
+        if ((bool)$this->config->crossBorderTradeEnabled($this->storeId)) {
+            return true;
+        } else {
+            return (abs($rate - $storeRate) < 0.00001);
+        }
+    }
+
+    /**
+     * Create AppliedTax data object based applied tax rates and tax amount
+     *
+     * @param float $rowTax
+     * @param array $appliedRate
+     * example:
+     *  [
+     *      'id' => 'id',
+     *      'percent' => 7.5,
+     *      'rates' => [
+     *          'code' => 'code',
+     *          'title' => 'title',
+     *          'percent' => 5.3,
+     *      ],
+     *  ]
+     * @return \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax
+     */
+    protected function getAppliedTax($rowTax, $appliedRate)
+    {
+        $appliedTaxBuilder = $this->taxDetailsItemBuilder->getAppliedTaxBuilder();
+        $appliedTaxRateBuilder = $appliedTaxBuilder->getAppliedTaxRateBuilder();
+        $appliedTaxBuilder->setAmount($rowTax);
+        $appliedTaxBuilder->setPercent($appliedRate['percent']);
+        $appliedTaxBuilder->setTaxRateKey($appliedRate['id']);
+
+        /** @var  AppliedTaxRate[] $rateDataObjects */
+        $rateDataObjects = [];
+        foreach ($appliedRate['rates'] as $rate) {
+            $appliedTaxRateBuilder->setPercent($rate['percent']);
+            $appliedTaxRateBuilder->setCode($rate['code']);
+            $appliedTaxRateBuilder->setTitle($rate['title']);
+            //Skipped position, priority and rule_id
+            $rateDataObjects[$rate['code']] = $appliedTaxRateBuilder->create();
+        }
+        $appliedTaxBuilder->setRates($rateDataObjects);
+        $appliedTax = $appliedTaxBuilder->create();
+        return $appliedTax;
+    }
+
+    /**
+     * Create AppliedTax data object based on applied tax rates and tax amount
+     *
+     * @param float $rowTax
+     * @param float $totalTaxRate
+     * @param array $appliedRates May contain multiple tax rates when catalog price includes tax
+     * example:
+     *  [
+     *      [
+     *          'id' => 'id1',
+     *          'percent' => 7.5,
+     *          'rates' => [
+     *              'code' => 'code1',
+     *              'title' => 'title1',
+     *              'percent' => 5.3,
+     *          ],
+     *      ],
+     *      [
+     *          'id' => 'id2',
+     *          'percent' => 8.5,
+     *          'rates' => [
+     *              'code' => 'code2',
+     *              'title' => 'title2',
+     *              'percent' => 7.3,
+     *          ],
+     *      ],
+     *  ]
+     * @return \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[]
+     */
+    protected function getAppliedTaxes($rowTax, $totalTaxRate, $appliedRates)
+    {
+        $appliedTaxBuilder = $this->taxDetailsItemBuilder->getAppliedTaxBuilder();
+        $appliedTaxRateBuilder = $appliedTaxBuilder->getAppliedTaxRateBuilder();
+        /** @var \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[] $appliedTaxes */
+        $appliedTaxes = [];
+        $totalAppliedAmount = 0;
+        foreach ($appliedRates as $appliedRate) {
+            if ($appliedRate['percent'] == 0) {
+                continue;
+            }
+
+            $appliedAmount = $rowTax / $totalTaxRate * $appliedRate['percent'];
+            //Use delta rounding to split tax amounts for each tax rates between items
+            $appliedAmount = $this->deltaRound(
+                $appliedAmount,
+                $appliedRate['id'],
+                true,
+                self::KEY_APPLIED_TAX_DELTA_ROUNDING
+            );
+            if ($totalAppliedAmount + $appliedAmount > $rowTax) {
+                $appliedAmount = $rowTax - $totalAppliedAmount;
+            }
+            $totalAppliedAmount += $appliedAmount;
+
+            $appliedTaxBuilder->setAmount($appliedAmount);
+            $appliedTaxBuilder->setPercent($appliedRate['percent']);
+            $appliedTaxBuilder->setTaxRateKey($appliedRate['id']);
+
+            /** @var  AppliedTaxRate[] $rateDataObjects */
+            $rateDataObjects = [];
+            foreach ($appliedRate['rates'] as $rate) {
+                $appliedTaxRateBuilder->setPercent($rate['percent']);
+                $appliedTaxRateBuilder->setCode($rate['code']);
+                $appliedTaxRateBuilder->setTitle($rate['title']);
+                //Skipped position, priority and rule_id
+                $rateDataObjects[$rate['code']] = $appliedTaxRateBuilder->create();
+            }
+            $appliedTaxBuilder->setRates($rateDataObjects);
+            $appliedTax = $appliedTaxBuilder->create();
+            $appliedTaxes[$appliedTax->getTaxRateKey()] = $appliedTax;
+        }
+
+        return $appliedTaxes;
+    }
+
+    /**
+     * Round price based on previous rounding operation delta
+     *
+     * @param float $price
+     * @param string $rate
+     * @param bool $direction
+     * @param string $type
+     * @return float
+     */
+    protected function deltaRound($price, $rate, $direction, $type = self::KEY_REGULAR_DELTA_ROUNDING)
+    {
+        if ($price) {
+            $rate = (string)$rate;
+            $type = $type . $direction;
+            // initialize the delta to a small number to avoid non-deterministic behavior with rounding of 0.5
+            $delta = isset($this->roundingDeltas[$type][$rate]) ?
+                $this->roundingDeltas[$type][$rate] :
+                0.000001;
+            $price += $delta;
+            $roundPrice = $this->calculationTool->round($price);
+            $this->roundingDeltas[$type][$rate] = $price - $roundPrice;
+            $price = $roundPrice;
+        }
+        return $price;
+    }
+
+    /**
+     * Given a store price that includes tax at the store rate, this function will back out the store's tax, and add in
+     * the customer's tax.  Returns this new price which is the customer's price including tax.
+     *
+     * @param float $storePriceInclTax
+     * @param float $storeRate
+     * @param float $customerRate
+     * @return float
+     */
+    protected function calculatePriceInclTax($storePriceInclTax, $storeRate, $customerRate)
+    {
+        $storeTax = $this->calculationTool->calcTaxAmount($storePriceInclTax, $storeRate, true, false);
+        $priceExclTax = $storePriceInclTax - $storeTax;
+        $customerTax = $this->calculationTool->calcTaxAmount($priceExclTax, $customerRate, false, false);
+        $customerPriceInclTax = $this->calculationTool->round($priceExclTax + $customerTax);
+        return $customerPriceInclTax;
+    }
+}
diff --git a/app/code/Magento/Tax/Model/Calculation/CalculatorFactory.php b/app/code/Magento/Tax/Model/Calculation/CalculatorFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..b042d865a8b111aa03cd15a1f2bf14c43d6d0c6a
--- /dev/null
+++ b/app/code/Magento/Tax/Model/Calculation/CalculatorFactory.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Model\Calculation;
+
+use \Magento\Customer\Service\V1\Data\Address;
+
+class CalculatorFactory
+{
+    /**
+     * Identifier constant for unit based calculation
+     */
+    const CALC_UNIT_BASE = 'UNIT_BASE_CALCULATION';
+
+    /**
+     * Identifier constant for row based calculation
+     */
+    const CALC_ROW_BASE = 'ROW_BASE_CALCULATION';
+
+    /**
+     * Identifier constant for total based calculation
+     */
+    const CALC_TOTAL_BASE = 'TOTAL_BASE_CALCULATION';
+
+    /**
+     * @var \Magento\Framework\ObjectManager
+     */
+    protected $objectManager;
+
+    /**
+     * Constructor
+     *
+     * @param \Magento\Framework\ObjectManager $objectManager
+     */
+    public function __construct(\Magento\Framework\ObjectManager $objectManager)
+    {
+        $this->objectManager = $objectManager;
+    }
+
+    /**
+     * Create new calculator
+     *
+     * @param string $type Type of calculator
+     * @param int $storeId
+     * @param Address $billingAddress
+     * @param Address $shippingAddress
+     * @param null|int $customerTaxClassId
+     * @param null|int $customerId
+     * @return \Magento\Tax\Model\Calculation\AbstractCalculator
+     * @throws \InvalidArgumentException
+     */
+    public function create(
+        $type,
+        $storeId,
+        Address $billingAddress = null,
+        Address $shippingAddress = null,
+        $customerTaxClassId = null,
+        $customerId = null
+    ) {
+        switch ($type) {
+            case self::CALC_UNIT_BASE:
+                $className = 'Magento\Tax\Model\Calculation\UnitBaseCalculator';
+                break;
+            case self::CALC_ROW_BASE:
+                $className = 'Magento\Tax\Model\Calculation\RowBaseCalculator';
+                break;
+            case self::CALC_TOTAL_BASE:
+                $className = 'Magento\Tax\Model\Calculation\TotalBaseCalculator';
+                break;
+            default:
+                throw new \InvalidArgumentException('Unknown calculation type: ' . $type);
+        }
+        /** @var \Magento\Tax\Model\Calculation\AbstractCalculator $calculator */
+        $calculator = $this->objectManager->create($className, ['storeId' => $storeId]);
+        if (null != $shippingAddress) {
+            $calculator->setShippingAddress($shippingAddress);
+        }
+        if (null != $billingAddress) {
+            $calculator->setBillingAddress($billingAddress);
+        }
+        if (null != $customerTaxClassId) {
+            $calculator->setCustomerTaxClassId($customerTaxClassId);
+        }
+        if (null != $customerId) {
+            $calculator->setCustomerId($customerTaxClassId);
+        }
+        return $calculator;
+    }
+}
diff --git a/app/code/Magento/Tax/Model/Calculation/RowBaseCalculator.php b/app/code/Magento/Tax/Model/Calculation/RowBaseCalculator.php
new file mode 100644
index 0000000000000000000000000000000000000000..a727a2de6552ff1a279dea852c0ccf280c8a31d4
--- /dev/null
+++ b/app/code/Magento/Tax/Model/Calculation/RowBaseCalculator.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Model\Calculation;
+
+use Magento\Tax\Model\Calculation;
+use Magento\Customer\Service\V1\Data\Address;
+use Magento\Tax\Service\V1\Data\QuoteDetails\Item as QuoteDetailsItem;
+
+class RowBaseCalculator extends AbstractAggregateCalculator
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function roundAmount($amount, $rate = null, $direction = null, $type = self::KEY_REGULAR_DELTA_ROUNDING)
+    {
+        return $this->calculationTool->round($amount);
+    }
+}
diff --git a/app/code/Magento/Tax/Model/Calculation/TotalBaseCalculator.php b/app/code/Magento/Tax/Model/Calculation/TotalBaseCalculator.php
new file mode 100644
index 0000000000000000000000000000000000000000..f018a2f17f94f0e5c2d3e12688c6aa64b4237830
--- /dev/null
+++ b/app/code/Magento/Tax/Model/Calculation/TotalBaseCalculator.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Model\Calculation;
+
+use Magento\Tax\Model\Calculation;
+use Magento\Customer\Service\V1\Data\Address;
+use Magento\Tax\Service\V1\Data\QuoteDetails\Item as QuoteDetailsItem;
+
+class TotalBaseCalculator extends AbstractAggregateCalculator
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function roundAmount($amount, $rate = null, $direction = null, $type = self::KEY_REGULAR_DELTA_ROUNDING)
+    {
+        return $this->deltaRound($amount, $rate, $direction, $type);
+    }
+}
diff --git a/app/code/Magento/Tax/Model/Calculation/UnitBaseCalculator.php b/app/code/Magento/Tax/Model/Calculation/UnitBaseCalculator.php
new file mode 100644
index 0000000000000000000000000000000000000000..f28de1c132647e5d8465aea2c4fdd24c19c27f8b
--- /dev/null
+++ b/app/code/Magento/Tax/Model/Calculation/UnitBaseCalculator.php
@@ -0,0 +1,159 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Model\Calculation;
+
+use Magento\Tax\Model\Calculation;
+use Magento\Customer\Service\V1\Data\Address;
+use Magento\Tax\Service\V1\Data\QuoteDetails\Item as QuoteDetailsItem;
+
+class UnitBaseCalculator extends AbstractCalculator
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function calculateWithTaxInPrice(QuoteDetailsItem $item, $quantity)
+    {
+        $taxRateRequest = $this->getAddressRateRequest()->setProductClassId(
+            $this->taxClassService->getTaxClassId($item->getTaxClassKey())
+        );
+        $rate = $this->calculationTool->getRate($taxRateRequest);
+        $storeRate = $storeRate = $this->calculationTool->getStoreRate($taxRateRequest, $this->storeId);
+
+        // Calculate $priceInclTax
+        $priceInclTax = $this->calculationTool->round($item->getUnitPrice());
+        if (!$this->isSameRateAsStore($rate, $storeRate)) {
+            $priceInclTax = $this->calculatePriceInclTax($priceInclTax, $storeRate, $rate);
+        }
+        $uniTax = $this->calculationTool->calcTaxAmount($priceInclTax, $rate, true, true);
+        $price = $priceInclTax - $uniTax;
+
+        //Handle discount
+        $discountTaxCompensationAmount = 0;
+        $applyTaxAfterDiscount = $this->config->applyTaxAfterDiscount($this->storeId);
+        $discountAmount = $item->getDiscountAmount();
+        if ($discountAmount && $applyTaxAfterDiscount) {
+            //TODO: handle originalDiscountAmount
+            $unitDiscountAmount = $discountAmount / $quantity;
+            $taxableAmount = max($priceInclTax - $unitDiscountAmount, 0);
+            $unitTaxAfterDiscount = $this->calculationTool->calcTaxAmount(
+                $taxableAmount,
+                $rate,
+                true,
+                true
+            );
+
+            // Set discount tax compensation
+            $unitDiscountTaxCompensationAmount = $uniTax - $unitTaxAfterDiscount;
+            $discountTaxCompensationAmount = $unitDiscountTaxCompensationAmount * $quantity;
+            $uniTax = $unitTaxAfterDiscount;
+        }
+        $rowTax = $uniTax * $quantity;
+
+        // Calculate applied taxes
+        /** @var  \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[] $appliedTaxes */
+        $appliedTaxes = [];
+        $appliedRates = $this->calculationTool->getAppliedRates($taxRateRequest);
+        $appliedTaxes = $this->getAppliedTaxes($rowTax, $rate, $appliedRates);
+
+        $this->taxDetailsItemBuilder->setCode($item->getCode());
+        $this->taxDetailsItemBuilder->setType($item->getType());
+        $this->taxDetailsItemBuilder->setRowTax($rowTax);
+        $this->taxDetailsItemBuilder->setPrice($price);
+        $this->taxDetailsItemBuilder->setPriceInclTax($priceInclTax);
+        $this->taxDetailsItemBuilder->setRowTotal($price * $quantity);
+        $this->taxDetailsItemBuilder->setRowTotalInclTax($priceInclTax * $quantity);
+        $this->taxDetailsItemBuilder->setDiscountTaxCompensationAmount($discountTaxCompensationAmount);
+        $this->taxDetailsItemBuilder->setAssociatedItemCode($item->getAssociatedItemCode());
+        $this->taxDetailsItemBuilder->setTaxPercent($rate);
+        $this->taxDetailsItemBuilder->setAppliedTaxes($appliedTaxes);
+        return $this->taxDetailsItemBuilder->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function calculateWithTaxNotInPrice(QuoteDetailsItem $item, $quantity)
+    {
+        $taxRateRequest = $this->getAddressRateRequest()->setProductClassId(
+            $this->taxClassService->getTaxClassId($item->getTaxClassKey())
+        );
+        $rate = $this->calculationTool->getRate($taxRateRequest);
+        $appliedRates = $this->calculationTool->getAppliedRates($taxRateRequest);
+
+        $applyTaxAfterDiscount = $this->config->applyTaxAfterDiscount($this->storeId);
+        $discountAmount = $item->getDiscountAmount();
+        $discountTaxCompensationAmount = 0;
+
+        // Calculate $price
+        $price = $this->calculationTool->round($item->getUnitPrice());
+        $unitTaxes = [];
+        $unitTaxesBeforeDiscount = [];
+        $appliedTaxes = [];
+        //Apply each tax rate separately
+        foreach ($appliedRates as $appliedRate) {
+            $taxId = $appliedRate['id'];
+            $taxRate = $appliedRate['percent'];
+            $unitTaxPerRate = $this->calculationTool->calcTaxAmount($price, $taxRate, false);
+            $unitTaxAfterDiscount = $unitTaxPerRate;
+
+            //Handle discount
+            if ($discountAmount && $applyTaxAfterDiscount) {
+                //TODO: handle originalDiscountAmount
+                $unitDiscountAmount = $discountAmount / $quantity;
+                $taxableAmount = max($price - $unitDiscountAmount, 0);
+                $unitTaxAfterDiscount = $this->calculationTool->calcTaxAmount(
+                    $taxableAmount,
+                    $taxRate,
+                    false,
+                    true
+                );
+            }
+            $appliedTaxes[$taxId] = $this->getAppliedTax(
+                $unitTaxAfterDiscount * $quantity,
+                $appliedRate
+            );
+
+            $unitTaxes[] = $unitTaxAfterDiscount;
+            $unitTaxesBeforeDiscount[] = $unitTaxPerRate;
+        }
+        $unitTax = array_sum($unitTaxes);
+        $unitTaxBeforeDiscount = array_sum($unitTaxesBeforeDiscount);
+
+        $rowTax = $unitTax * $quantity;
+        $priceInclTax = $price + $unitTaxBeforeDiscount;
+
+        $this->taxDetailsItemBuilder->setCode($item->getCode());
+        $this->taxDetailsItemBuilder->setType($item->getType());
+        $this->taxDetailsItemBuilder->setRowTax($rowTax);
+        $this->taxDetailsItemBuilder->setPrice($price);
+        $this->taxDetailsItemBuilder->setPriceInclTax($priceInclTax);
+        $this->taxDetailsItemBuilder->setRowTotal($price * $quantity);
+        $this->taxDetailsItemBuilder->setRowTotalInclTax($priceInclTax * $quantity);
+        $this->taxDetailsItemBuilder->setDiscountTaxCompensationAmount($discountTaxCompensationAmount);
+        $this->taxDetailsItemBuilder->setAssociatedItemCode($item->getAssociatedItemCode());
+        $this->taxDetailsItemBuilder->setTaxPercent($rate);
+        $this->taxDetailsItemBuilder->setAppliedTaxes($appliedTaxes);
+        return $this->taxDetailsItemBuilder->create();
+    }
+}
diff --git a/app/code/Magento/Tax/Model/Observer.php b/app/code/Magento/Tax/Model/Observer.php
index 494460f693dd9bbbd5a4c701c2c738367775d753..571b44e441e3cecaf1295d8d9c8691d60a64e34b 100644
--- a/app/code/Magento/Tax/Model/Observer.php
+++ b/app/code/Magento/Tax/Model/Observer.php
@@ -112,6 +112,14 @@ class Observer
             $order->setAppliedTaxes($taxes);
             $order->setConvertingFromQuote(true);
         }
+
+        $itemAppliedTaxes = $address->getItemsAppliedTaxes();
+        if (is_array($itemAppliedTaxes)) {
+            if (is_array($order->getItemAppliedTaxes())) {
+                $itemAppliedTaxes = array_merge($order->getItemAppliedTaxes(), $itemAppliedTaxes);
+            }
+            $order->setItemAppliedTaxes($itemAppliedTaxes);
+        }
     }
 
     /**
@@ -128,7 +136,7 @@ class Observer
             return;
         }
 
-        $getTaxesForItems = $order->getQuote()->getTaxesForItems();
+        $getTaxesForItems = $order->getItemAppliedTaxes();
         $taxes = $order->getAppliedTaxes();
 
         $ratesIdQuoteItemId = array();
@@ -139,18 +147,32 @@ class Observer
             foreach ($taxesArray as $rates) {
                 if (count($rates['rates']) == 1) {
                     $ratesIdQuoteItemId[$rates['id']][] = array(
-                        'id' => $quoteItemId,
+                        'id' => $rates['item_id'],
                         'percent' => $rates['percent'],
-                        'code' => $rates['rates'][0]['code']
+                        'code' => $rates['rates'][0]['code'],
+                        'associated_item_id' => $rates['associated_item_id'],
+                        'item_type' => $rates['item_type'],
+                        'amount' => $rates['amount'],
+                        'base_amount' => $rates['base_amount'],
+                        'real_amount' => $rates['amount'],
+                        'real_base_amount' => $rates['base_amount'],
                     );
                 } else {
                     $percentDelta = $rates['percent'];
                     $percentSum = 0;
                     foreach ($rates['rates'] as $rate) {
+                        $real_amount = $rates['amount'] * $rate['percent'] / $rates['percent'];
+                        $real_base_amount = $rates['base_amount'] * $rate['percent'] / $rates['percent'];
                         $ratesIdQuoteItemId[$rates['id']][] = array(
-                            'id' => $quoteItemId,
+                            'id' => $rates['item_id'],
                             'percent' => $rate['percent'],
-                            'code' => $rate['code']
+                            'code' => $rate['code'],
+                            'associated_item_id' => $rates['associated_item_id'],
+                            'item_type' => $rates['item_type'],
+                            'amount' => $rates['amount'],
+                            'base_amount' => $rates['base_amount'],
+                            'real_amount' => $real_amount,
+                            'real_base_amount' => $real_base_amount,
                         );
                         $percentSum += $rate['percent'];
                     }
@@ -202,17 +224,32 @@ class Observer
                 if (isset($ratesIdQuoteItemId[$id])) {
                     foreach ($ratesIdQuoteItemId[$id] as $quoteItemId) {
                         if ($quoteItemId['code'] == $tax['code']) {
-                            $item = $order->getItemByQuoteItemId($quoteItemId['id']);
-                            if ($item) {
-                                $data = array(
-                                    'item_id' => $item->getId(),
-                                    'tax_id' => $result->getTaxId(),
-                                    'tax_percent' => $quoteItemId['percent']
-                                );
-                                /** @var $taxItem \Magento\Tax\Model\Sales\Order\Tax\Item */
-                                $taxItem = $this->_taxItemFactory->create();
-                                $taxItem->setData($data)->save();
+                            $itemId = null;
+                            $associatedItemId = null;
+                            if (isset($quoteItemId['id'])) {
+                                //This is a product item
+                                $item = $order->getItemByQuoteItemId($quoteItemId['id']);
+                                $itemId = $item->getId();
+                            } elseif (isset($quoteItemId['associated_item_id'])) {
+                                //This item is associated with a product item
+                                $item = $order->getItemByQuoteItemId($quoteItemId['associated_item_id']);
+                                $associatedItemId = $item->getId();
                             }
+
+                            $data = array(
+                                'item_id' => $itemId,
+                                'tax_id' => $result->getTaxId(),
+                                'tax_percent' => $quoteItemId['percent'],
+                                'associated_item_id' => $associatedItemId,
+                                'amount' => $quoteItemId['amount'],
+                                'base_amount' => $quoteItemId['base_amount'],
+                                'real_amount' => $quoteItemId['real_amount'],
+                                'real_base_amount' => $quoteItemId['real_base_amount'],
+                                'taxable_item_type' => $quoteItemId['item_type'],
+                            );
+                            /** @var $taxItem \Magento\Tax\Model\Sales\Order\Tax\Item */
+                            $taxItem = $this->_taxItemFactory->create();
+                            $taxItem->setData($data)->save();
                         }
                     }
                 }
diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php
new file mode 100644
index 0000000000000000000000000000000000000000..a888602de26d3f67901f0e7f52b4334053332f70
--- /dev/null
+++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php
@@ -0,0 +1,819 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Model\Sales\Total\Quote;
+
+use Magento\Store\Model\Store;
+use Magento\Sales\Model\Quote\Address;
+use Magento\Sales\Model\Quote\Address\Total\AbstractTotal;
+use Magento\Tax\Model\Calculation;
+use Magento\Sales\Model\Quote\Item\AbstractItem;
+use Magento\Customer\Service\V1\Data\AddressBuilder;
+use Magento\Tax\Service\V1\Data\QuoteDetailsBuilder;
+use Magento\Tax\Service\V1\Data\QuoteDetails\ItemBuilder;
+use Magento\Tax\Service\V1\Data\QuoteDetails\Item as ItemDataObject;
+use Magento\Tax\Service\V1\Data\TaxClassKey;
+use Magento\Tax\Service\V1\Data\TaxDetails;
+use Magento\Tax\Service\V1\Data\QuoteDetails;
+use Magento\Tax\Service\V1\Data\TaxDetails\Item as ItemTaxDetails;
+use Magento\Framework\Object;
+
+/**
+ * Tax totals calculation model
+ */
+class CommonTaxCollector extends AbstractTotal
+{
+    /**#@+
+     * Constants defined for type of items
+     */
+    const ITEM_TYPE_SHIPPING = 'shipping';
+    const ITEM_TYPE_PRODUCT = 'product';
+    /**#@-*/
+
+    /**
+     * Constant for shipping item code
+     */
+    const ITEM_CODE_SHIPPING = 'shipping';
+
+    /**#@+
+     * Constants for array keys
+     */
+    const KEY_ITEM = 'item';
+    const KEY_BASE_ITEM = 'base_item';
+    /**#@-*/
+
+    /**#@+
+     * Constants for fields in associated taxables array
+     */
+    const KEY_ASSOCIATED_TAXABLE_TYPE = 'type';
+    const KEY_ASSOCIATED_TAXABLE_CODE = 'code';
+    const KEY_ASSOCIATED_TAXABLE_UNIT_PRICE = 'unit_price';
+    const KEY_ASSOCIATED_TAXABLE_BASE_UNIT_PRICE = 'base_unit_price';
+    const KEY_ASSOCIATED_TAXABLE_QUANTITY = 'quantity';
+    const KEY_ASSOCIATED_TAXABLE_TAX_CLASS_ID = 'tax_class_id';
+    const KEY_ASSOCIATED_TAXABLE_PRICE_INCLUDES_TAX = 'price_includes_tax';
+    const KEY_ASSOCIATED_TAXABLE_ASSOCIATION_ITEM_CODE = 'associated_item_code';
+    /**#@-*/
+
+    /**
+     * When an extra taxable item is associated with quote and not with an item, this value
+     * is used as associated item code
+     */
+    const ASSOCIATION_ITEM_CODE_FOR_QUOTE = 'quote';
+
+    /**#@+
+     * Constants for fields in tax details for associated taxable items
+     */
+    const KEY_TAX_DETAILS_TYPE = 'type';
+    const KEY_TAX_DETAILS_CODE = 'code';
+    const KEY_TAX_DETAILS_PRICE_EXCL_TAX = 'price_excl_tax';
+    const KEY_TAX_DETAILS_BASE_PRICE_EXCL_TAX = 'base_price_excl_tax';
+    const KEY_TAX_DETAILS_PRICE_INCL_TAX = 'price_incl_tax';
+    const KEY_TAX_DETAILS_BASE_PRICE_INCL_TAX = 'base_price_incl_tax';
+    const KEY_TAX_DETAILS_ROW_TOTAL = 'row_total_excl_tax';
+    const KEY_TAX_DETAILS_BASE_ROW_TOTAL = 'base_row_total_excl_tax';
+    const KEY_TAX_DETAILS_ROW_TOTAL_INCL_TAX = 'row_total_incl_tax';
+    const KEY_TAX_DETAILS_BASE_ROW_TOTAL_INCL_TAX = 'base_row_total_incl_tax';
+    const KEY_TAX_DETAILS_TAX_PERCENT = 'tax_percent';
+    const KEY_TAX_DETAILS_ROW_TAX = 'row_tax';
+    const KEY_TAX_DETAILS_BASE_ROW_TAX = 'base_row_tax';
+    const KEY_TAX_DETAILS_APPLIED_TAXES = 'applied_taxes';
+    /**#@-*/
+
+    /**
+     * Static counter
+     *
+     * @var int
+     */
+    protected static $counter = 0;
+
+    /**
+     * Tax configuration object
+     *
+     * @var \Magento\Tax\Model\Config
+     */
+    protected $_config;
+
+    /**
+     * @var Store
+     */
+    protected $_store;
+
+    /**
+     * Tax calculation service, the collector will call the service which performs the actual calculation
+     *
+     * @var \Magento\Tax\Service\V1\TaxCalculationService
+     */
+    protected $taxCalculationService;
+
+    /**
+     * Builder to create QuoteDetails as input to tax calculation service
+     *
+     * @var \Magento\Tax\Service\V1\Data\QuoteDetailsBuilder
+     */
+    protected $quoteDetailsBuilder;
+
+    /**
+     * Class constructor
+     *
+     * @param \Magento\Tax\Model\Config $taxConfig
+     * @param \Magento\Tax\Service\V1\TaxCalculationService $taxCalculationService
+     * @param \Magento\Tax\Service\V1\Data\QuoteDetailsBuilder $quoteDetailsBuilder
+     */
+    public function __construct(
+        \Magento\Tax\Model\Config $taxConfig,
+        \Magento\Tax\Service\V1\TaxCalculationService $taxCalculationService,
+        \Magento\Tax\Service\V1\Data\QuoteDetailsBuilder $quoteDetailsBuilder
+    ) {
+        $this->taxCalculationService = $taxCalculationService;
+        $this->quoteDetailsBuilder = $quoteDetailsBuilder;
+        $this->_config = $taxConfig;
+    }
+
+    /**
+     * Map Address to Address data object
+     *
+     * @param AddressBuilder $addressBuilder
+     * @param Address $address
+     * @return \Magento\Customer\Service\V1\Data\Address
+     */
+    public function mapAddress(AddressBuilder $addressBuilder, Address $address)
+    {
+        $addressBuilder->setCountryId($address->getCountryId());
+        $addressBuilder->setRegion(
+            $addressBuilder->getRegionBuilder()
+                ->setRegionId($address->getRegionId())
+                ->create()
+        );
+        $addressBuilder->setPostcode($address->getPostcode());
+        $addressBuilder->setCity($address->getCity());
+        $addressBuilder->setStreet($address->getStreet());
+
+        return $addressBuilder->create();
+    }
+
+    /**
+     * Increment and return static counter. This function is intended to be used to generate temporary
+     * id for an item.
+     *
+     * @return int
+     */
+    protected function getNextIncrement()
+    {
+        return ++self::$counter;
+    }
+
+    /**
+     * Map an item to item data object
+     *
+     * @param ItemBuilder $itemBuilder
+     * @param AbstractItem $item
+     * @param bool $priceIncludesTax
+     * @param bool $useBaseCurrency
+     * @param string $parentCode
+     * @return ItemDataObject
+     */
+    public function mapItem(
+        ItemBuilder $itemBuilder,
+        AbstractItem $item,
+        $priceIncludesTax,
+        $useBaseCurrency,
+        $parentCode = null
+    ) {
+        if (!$item->getTaxCalculationItemId()) {
+            $sequence = 'sequence-' . $this->getNextIncrement();
+            $item->setTaxCalculationItemId($sequence);
+        }
+        $itemBuilder->setCode($item->getTaxCalculationItemId());
+        $itemBuilder->setQuantity($item->getQty());
+        $itemBuilder->setTaxClassKey(
+            $itemBuilder->getTaxClassKeyBuilder()
+                ->setType(TaxClassKey::TYPE_ID)
+                ->setValue($item->getProduct()->getTaxClassId())
+                ->create()
+        );
+
+        $itemBuilder->setTaxIncluded($priceIncludesTax);
+        $itemBuilder->setType(self::ITEM_TYPE_PRODUCT);
+
+        if ($useBaseCurrency) {
+            if (!$item->getBaseTaxCalculationPrice()) {
+                $item->setBaseTaxCalculationPrice($item->getBaseCalculationPriceOriginal());
+            }
+            $itemBuilder->setUnitPrice($item->getBaseTaxCalculationPrice());
+            $itemBuilder->setDiscountAmount($item->getBaseDiscountAmount());
+        } else {
+            if (!$item->getTaxCalculationPrice()) {
+                $item->setTaxCalculationPrice($item->getCalculationPriceOriginal());
+            }
+            $itemBuilder->setUnitPrice($item->getTaxCalculationPrice());
+            $itemBuilder->setDiscountAmount($item->getDiscountAmount());
+        }
+
+        $itemBuilder->setParentCode($parentCode);
+
+        return $itemBuilder->create();
+    }
+
+    /**
+     * Map item extra taxables
+     *
+     * @param ItemBuilder $itemBuilder
+     * @param AbstractItem $item
+     * @param bool $priceIncludesTax
+     * @param bool $useBaseCurrency
+     * @return ItemDataObject[]
+     */
+    public function mapItemExtraTaxables(
+        ItemBuilder $itemBuilder,
+        AbstractItem $item,
+        $priceIncludesTax,
+        $useBaseCurrency
+    ) {
+        $itemDataObjects = [];
+        $extraTaxables = $item->getAssociatedTaxables();
+        if (!$extraTaxables) {
+            return [];
+        }
+
+        foreach ($extraTaxables as $extraTaxable) {
+            $extraTaxableIncludesTax =
+                isset($extraTaxable['price_includes_tax']) ? $extraTaxable['price_includes_tax'] : $priceIncludesTax;
+
+            $itemBuilder->setCode($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_CODE]);
+            $itemBuilder->setType($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_TYPE]);
+            $itemBuilder->setQuantity($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_QUANTITY]);
+            $itemBuilder->setTaxClassKey(
+                $itemBuilder->getTaxClassKeyBuilder()
+                    ->setType(TaxClassKey::TYPE_ID)
+                    ->setValue($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_TAX_CLASS_ID])
+                    ->create()
+            );
+            if ($useBaseCurrency) {
+                $unitPrice = $extraTaxable[self::KEY_ASSOCIATED_TAXABLE_BASE_UNIT_PRICE];
+            } else {
+                $unitPrice = $extraTaxable[self::KEY_ASSOCIATED_TAXABLE_UNIT_PRICE];
+            }
+            $itemBuilder->setUnitPrice($unitPrice);
+            $itemBuilder->setTaxIncluded($extraTaxableIncludesTax);
+            $itemBuilder->setAssociatedItemCode($item->getTaxCalculationItemId());
+            $itemDataObjects[] = $itemBuilder->create();
+        }
+
+        return $itemDataObjects;
+    }
+
+    /**
+     * Add quote items to quoteDetailsBuilder
+     *
+     * @param Address $address
+     * @param bool $useBaseCurrency
+     * @param bool $priceIncludesTax
+     * @return ItemDataObject[]
+     */
+    public function mapItems(
+        Address $address,
+        $priceIncludesTax,
+        $useBaseCurrency
+    ) {
+        $items = $this->_getAddressItems($address);
+        if (!count($items)) {
+            return [];
+        }
+
+        //Populate with items
+        $itemBuilder = $this->quoteDetailsBuilder->getItemBuilder();
+        $itemDataObjects = [];
+        foreach ($items as $item) {
+            if ($item->getParentItem()) {
+                continue;
+            }
+
+            if ($item->getHasChildren() && $item->isChildrenCalculated()) {
+                $parentItemDataObject = $this->mapItem($itemBuilder, $item, $priceIncludesTax, $useBaseCurrency);
+                $itemDataObjects[] = $parentItemDataObject;
+                foreach ($item->getChildren() as $child) {
+                    $childItemDataObject = $this->mapItem(
+                        $itemBuilder,
+                        $child,
+                        $priceIncludesTax,
+                        $useBaseCurrency,
+                        $parentItemDataObject->getCode()
+                    );
+                    $itemDataObjects[] = $childItemDataObject;
+                    $extraTaxableItems = $this->mapItemExtraTaxables(
+                        $itemBuilder,
+                        $item,
+                        $priceIncludesTax,
+                        $useBaseCurrency
+                    );
+                    $itemDataObjects = array_merge($itemDataObjects, $extraTaxableItems);
+                }
+            } else {
+                $itemDataObject = $this->mapItem($itemBuilder, $item, $priceIncludesTax, $useBaseCurrency);
+                $itemDataObjects[] = $itemDataObject;
+                $extraTaxableItems = $this->mapItemExtraTaxables(
+                    $itemBuilder,
+                    $item,
+                    $priceIncludesTax,
+                    $useBaseCurrency
+                );
+                $itemDataObjects = array_merge($itemDataObjects, $extraTaxableItems);
+            }
+        }
+
+        return $itemDataObjects;
+    }
+
+    /**
+     * Populate the quote details builder with address information
+     *
+     * @param QuoteDetailsBuilder $quoteDetailsBuilder
+     * @param Address $address
+     * @return QuoteDetailsBuilder
+     */
+    public function populateAddressData(QuoteDetailsBuilder $quoteDetailsBuilder, Address $address)
+    {
+        $addressBuilder = $this->quoteDetailsBuilder->getAddressBuilder();
+
+        //Set billing address
+        $this->quoteDetailsBuilder->setBillingAddress(
+            $this->mapAddress($addressBuilder, $address->getQuote()->getBillingAddress())
+        );
+        //Set shipping address
+        $this->quoteDetailsBuilder->setShippingAddress(
+            $this->mapAddress($addressBuilder, $address)
+        );
+
+        return $quoteDetailsBuilder;
+    }
+
+    /**
+     * @param Address $address
+     * @param bool $useBaseCurrency
+     * @return \Magento\Tax\Service\V1\Data\QuoteDetails\Item
+     */
+    public function getShippingDataObject(Address $address, $useBaseCurrency)
+    {
+        if (!$address->getShippingTaxCalculationAmount() || $address->getShippingTaxCalculationAmount() <= 0) {
+            //Save the original shipping amount because shipping amount will be overridden
+            //with shipping amount excluding tax
+            $address->setShippingTaxCalculationAmount($address->getShippingAmount());
+            $address->setBaseShippingTaxCalculationAmount($address->getBaseShippingAmount());
+        }
+        if ($address->getShippingTaxCalculationAmount() > 0) {
+            $itemBuilder = $this->quoteDetailsBuilder->getItemBuilder();
+            $itemBuilder->setType(self::ITEM_TYPE_SHIPPING);
+            $itemBuilder->setCode(self::ITEM_CODE_SHIPPING);
+            $itemBuilder->setQuantity(1);
+            if ($useBaseCurrency) {
+                $itemBuilder->setUnitPrice($address->getBaseShippingTaxCalculationAmount());
+            } else {
+                $itemBuilder->setUnitPrice($address->getShippingTaxCalculationAmount());
+            }
+            if ($address->getShippingDiscountAmount()) {
+                if ($useBaseCurrency) {
+                    $itemBuilder->setDiscountAmount($address->getBaseShippingDiscountAmount());
+                } else {
+                    $itemBuilder->setDiscountAmount($address->getShippingDiscountAmount());
+                }
+            }
+            $itemBuilder->setTaxClassKey(
+                $itemBuilder->getTaxClassKeyBuilder()
+                    ->setType(TaxClassKey::TYPE_ID)
+                    ->setValue($this->_config->getShippingTaxClass($this->_store))
+                    ->create()
+            );
+            $itemBuilder->setTaxIncluded($this->_config->shippingPriceIncludesTax($this->_store));
+            return $itemBuilder->create();
+        }
+        return null;
+    }
+
+    /**
+     * Populate QuoteDetails object from Address object
+     *
+     * @param Address $address
+     * @param ItemDataObject[] $itemDataObjects
+     * @return \Magento\Tax\Service\V1\Data\QuoteDetails
+     */
+    protected function prepareQuoteDetails(Address $address, $itemDataObjects)
+    {
+        $items = $this->_getAddressItems($address);
+        if (!count($items)) {
+            return $this->quoteDetailsBuilder->create();
+        }
+
+        $this->populateAddressData($this->quoteDetailsBuilder, $address);
+
+        //Set customer tax class
+        $this->quoteDetailsBuilder->setCustomerTaxClassKey(
+            $this->quoteDetailsBuilder->getTaxClassKeyBuilder()
+                ->setType(TaxClassKey::TYPE_ID)
+                ->setValue($address->getQuote()->getCustomerTaxClassId())
+                ->create()
+        );
+        $this->quoteDetailsBuilder->setItems($itemDataObjects);
+
+        $quoteDetails = $this->quoteDetailsBuilder->create();
+        return $quoteDetails;
+    }
+
+    /**
+     * Organize tax details by type and by item code
+     *
+     * @param TaxDetails $taxDetails
+     * @param TaxDetails $baseTaxDetails
+     * @return array
+     */
+    protected function organizeItemTaxDetailsByType(TaxDetails $taxDetails, TaxDetails $baseTaxDetails)
+    {
+        /** @var \Magento\Tax\Service\V1\Data\TaxDetails\Item[] $keyedItems */
+        $keyedItems = [];
+        foreach ($taxDetails->getItems() as $item) {
+            $keyedItems[$item->getCode()] = $item;
+        }
+        /** @var \Magento\Tax\Service\V1\Data\TaxDetails\Item[] $baseKeyedItems */
+        $baseKeyedItems = [];
+        foreach ($baseTaxDetails->getItems() as $item) {
+            $baseKeyedItems[$item->getCode()] = $item;
+        }
+
+        $itemsByType = [];
+        foreach ($keyedItems as $code => $item) {
+            $baseItem = $baseKeyedItems[$code];
+            $itemType = $item->getType();
+            $itemsByType[$itemType][$code] = [self::KEY_ITEM => $item, self::KEY_BASE_ITEM => $baseItem];
+        }
+
+        return $itemsByType;
+    }
+
+    /**
+     * Process product items in the quote.
+     * Set the following aggregated values in the quote object:
+     * subtotal, subtotalInclTax, tax, hidden_tax,
+     *
+     * @param Address $address
+     * @param array $itemTaxDetails
+     * @return $this
+     */
+    protected function processProductItems(Address $address, array $itemTaxDetails)
+    {
+        /** @var AbstractItem[] $keyedAddressItems */
+        $keyedAddressItems = [];
+        foreach ($this->_getAddressItems($address) as $addressItem) {
+            $keyedAddressItems[$addressItem->getTaxCalculationItemId()] = $addressItem;
+        }
+
+        $subtotal = $baseSubtotal = 0;
+        $hiddenTax = $baseHiddenTax = 0;
+        $tax = $baseTax = 0;
+        $subtotalInclTax = $baseSubtotalInclTax = 0;
+
+        foreach ($itemTaxDetails as $code => $itemTaxDetail) {
+            /** @var ItemTaxDetails $taxDetail */
+            $taxDetail = $itemTaxDetail[self::KEY_ITEM];
+            /** @var ItemTaxDetails $baseTaxDetail */
+            $baseTaxDetail = $itemTaxDetail[self::KEY_BASE_ITEM];
+            $quoteItem = $keyedAddressItems[$code];
+            $this->updateItemTaxInfo($quoteItem, $taxDetail, $baseTaxDetail);
+
+            //Update aggregated values
+            if ($quoteItem->getHasChildren() && $quoteItem->isChildrenCalculated()) {
+                //avoid double counting
+                continue;
+            }
+            $subtotal += $taxDetail->getRowTotal();
+            $baseSubtotal += $baseTaxDetail->getRowTotal();
+            $hiddenTax += $taxDetail->getDiscountTaxCompensationAmount();
+            $baseHiddenTax += $baseTaxDetail->getDiscountTaxCompensationAmount();
+            $tax += $taxDetail->getRowTax();
+            $baseTax += $baseTaxDetail->getRowTax();
+            $subtotalInclTax += $taxDetail->getRowTotalInclTax();
+            $baseSubtotalInclTax += $baseTaxDetail->getRowTotalInclTax();
+        }
+
+        //Set aggregated values
+        $address->setTotalAmount('subtotal', $subtotal);
+        $address->setBaseTotalAmount('subtotal', $baseSubtotal);
+        $address->setTotalAmount('tax', $tax);
+        $address->setBaseTotalAmount('tax', $baseTax);
+        $address->setTotalAmount('hidden_tax', $hiddenTax);
+        $address->setBaseTotalAmount('hidden_tax', $baseHiddenTax);
+
+        $address->setSubtotalInclTax($subtotalInclTax);
+        $address->setBaseSubtotalInclTax($baseSubtotalInclTax);
+
+        return $this;
+    }
+
+    /**
+     * Process applied taxes for items and quote
+     *
+     * @param Address $address
+     * @param array $itemsByType
+     * @return $this
+     */
+    protected function processAppliedTaxes(Address $address, Array $itemsByType)
+    {
+        $address->setAppliedTaxes([]);
+        $allAppliedTaxesArray = [];
+
+        /** @var AbstractItem[] $keyedAddressItems */
+        $keyedAddressItems = [];
+        foreach ($this->_getAddressItems($address) as $addressItem) {
+            $keyedAddressItems[$addressItem->getTaxCalculationItemId()] = $addressItem;
+        }
+
+        foreach ($itemsByType as $itemType => $items) {
+            foreach ($items as $itemTaxCalculationId => $itemTaxDetails) {
+                /** @var ItemTaxDetails $taxDetails */
+                $taxDetails = $itemTaxDetails[self::KEY_ITEM];
+                $baseTaxDetails = $itemTaxDetails[self::KEY_BASE_ITEM];
+
+                $appliedTaxes = $taxDetails->getAppliedTaxes();
+                $baseAppliedTaxes = $baseTaxDetails->getAppliedTaxes();
+
+                $itemType = $taxDetails->getType();
+                $itemId = null;
+                $associatedItemId = null;
+                if ($itemType == self::ITEM_TYPE_PRODUCT) {
+                    //Use item id instead of tax calculation id
+                    $itemId = $keyedAddressItems[$itemTaxCalculationId]->getId();
+                } else {
+                    if ($taxDetails->getAssociatedItemCode()
+                        && $taxDetails->getAssociatedItemCode() != self::ASSOCIATION_ITEM_CODE_FOR_QUOTE) {
+                        //This item is associated with a product item
+                        $associatedItemId = $keyedAddressItems[$taxDetails->getAssociatedItemCode()]->getId();
+                    } else {
+                        //This item is associated with an order, e.g., shipping, etc.
+                        $itemId = null;
+                    }
+                }
+                $extraInfo = [
+                    'item_id' => $itemId,
+                    'item_type' => $itemType,
+                    'associated_item_id' => $associatedItemId,
+                ];
+
+                $appliedTaxesArray = $this->convertAppliedTaxes($appliedTaxes, $baseAppliedTaxes, $extraInfo);
+
+                if ($itemType == self::ITEM_TYPE_PRODUCT) {
+                    $quoteItem = $keyedAddressItems[$itemTaxCalculationId];
+                    $quoteItem->setAppliedTaxes($appliedTaxesArray);
+                }
+
+                $allAppliedTaxesArray[$itemTaxCalculationId] = $appliedTaxesArray;
+
+                foreach ($appliedTaxesArray as $appliedTaxArray) {
+                    $this->_saveAppliedTaxes(
+                        $address,
+                        [$appliedTaxArray],
+                        $appliedTaxArray['amount'],
+                        $appliedTaxArray['base_amount'],
+                        $appliedTaxArray['percent']
+                    );
+                }
+            }
+        }
+
+        $address->setItemsAppliedTaxes($allAppliedTaxesArray);
+
+        return $this;
+    }
+
+    /**
+     * Update tax related fields for quote item
+     *
+     * @param AbstractItem $quoteItem
+     * @param ItemTaxDetails $itemTaxDetails
+     * @param ItemTaxDetails $baseItemTaxDetails
+     * @return $this
+     */
+    public function updateItemTaxInfo($quoteItem, $itemTaxDetails, $baseItemTaxDetails)
+    {
+        //The price should be base price
+        $quoteItem->setPrice($baseItemTaxDetails->getPrice());
+        $quoteItem->setConvertedPrice($itemTaxDetails->getPrice());
+        $quoteItem->setPriceInclTax($itemTaxDetails->getPriceInclTax());
+        $quoteItem->setRowTotal($itemTaxDetails->getRowTotal());
+        $quoteItem->setRowTotalInclTax($itemTaxDetails->getRowTotalInclTax());
+        $quoteItem->setTaxAmount($itemTaxDetails->getRowTax());
+        $quoteItem->setTaxPercent($itemTaxDetails->getTaxPercent());
+        $quoteItem->setHiddenTaxAmount($itemTaxDetails->getDiscountTaxCompensationAmount());
+
+        $quoteItem->setBasePrice($baseItemTaxDetails->getPrice());
+        $quoteItem->setBasePriceInclTax($baseItemTaxDetails->getPriceInclTax());
+        $quoteItem->setBaseRowTotal($baseItemTaxDetails->getRowTotal());
+        $quoteItem->setBaseRowTotalInclTax($baseItemTaxDetails->getRowTotalInclTax());
+        $quoteItem->setBaseTaxAmount($baseItemTaxDetails->getRowTax());
+        $quoteItem->setTaxPercent($baseItemTaxDetails->getTaxPercent());
+        $quoteItem->setBaseHiddenTaxAmount($baseItemTaxDetails->getDiscountTaxCompensationAmount());
+
+        //Set discount calculation price, this may be needed by discount collector
+        if ($this->_config->discountTax($this->_store)) {
+            $quoteItem->setDiscountCalculationPrice($itemTaxDetails->getPriceInclTax());
+            $quoteItem->setBaseDiscountCalculationPrice($baseItemTaxDetails->getPriceInclTax());
+        } else {
+            $quoteItem->setDiscountCalculationPrice($itemTaxDetails->getPrice());
+            $quoteItem->setBaseDiscountCalculationPrice($baseItemTaxDetails->getPrice());
+        }
+
+        return $this;
+    }
+
+    /**
+     * Update tax related fields for shipping
+     *
+     * @param Address $address
+     * @param \Magento\Tax\Service\V1\Data\TaxDetails\Item $shippingTaxDetails
+     * @param \Magento\Tax\Service\V1\Data\TaxDetails\Item $baseShippingTaxDetails
+     * @return $this
+     */
+    protected function processShippingTaxInfo(Address $address, $shippingTaxDetails, $baseShippingTaxDetails)
+    {
+        $address->setTotalAmount('shipping', $shippingTaxDetails->getRowTotal());
+        $address->setBaseTotalAmount('shipping', $baseShippingTaxDetails->getRowTotal());
+        $address->setTotalAmount('shipping_hidden_tax', $shippingTaxDetails->getDiscountTaxCompensationAmount());
+        $address->setBaseTotalAmount('shipping_hidden_tax', $baseShippingTaxDetails->getDiscountTaxCompensationAmount());
+
+        $address->setShippingInclTax($shippingTaxDetails->getRowTotalInclTax());
+        $address->setBaseShippingInclTax($baseShippingTaxDetails->getRowTotalInclTax());
+        $address->setShippingTaxAmount($shippingTaxDetails->getRowTax());
+        $address->setBaseShippingTaxAmount($baseShippingTaxDetails->getRowTax());
+
+        //Add the shipping tax to total tax amount
+        $address->addTotalAmount('tax', $shippingTaxDetails->getRowTax());
+        $address->addBaseTotalAmount('tax', $baseShippingTaxDetails->getRowTax());
+
+        if ($this->_config->discountTax($this->_store)) {
+            $address->setShippingAmountForDiscount($shippingTaxDetails->getRowTotalInclTax());
+            $address->setBaseShippingAmountForDiscount($baseShippingTaxDetails->getRowTotalInclTax());
+        }
+
+        return $this;
+    }
+
+    /**
+     * Convert appliedTax data object from tax calculation service to internal array format
+     *
+     * @param \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[] $appliedTaxes
+     * @param \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[] $baseAppliedTaxes
+     * @param array $extraInfo
+     * @return array
+     */
+    public function convertAppliedTaxes($appliedTaxes, $baseAppliedTaxes, $extraInfo = [])
+    {
+        $appliedTaxesArray = [];
+
+        if (!$appliedTaxes || !$baseAppliedTaxes) {
+            return $appliedTaxesArray;
+        }
+
+        foreach ($appliedTaxes as $taxId => $appliedTax) {
+            $baseAppliedTax = $baseAppliedTaxes[$taxId];
+            $rateDataObjects = $appliedTax->getRates();
+
+            $rates = [];
+            foreach ($rateDataObjects as $rateDataObject) {
+                $rates[] = [
+                    'percent' => $rateDataObject->getPercent(),
+                    'code' => $rateDataObject->getCode(),
+                    'title' => $rateDataObject->getTitle(),
+                ];
+            }
+
+            $appliedTaxArray = [
+                'amount' => $appliedTax->getAmount(),
+                'base_amount' => $baseAppliedTax->getAmount(),
+                'percent' => $appliedTax->getPercent(),
+                'id' => $appliedTax->getTaxRateKey(),
+                'rates' => $rates,
+            ];
+            if (!empty($extraInfo)) {
+                $appliedTaxArray = array_merge($appliedTaxArray, $extraInfo);
+            }
+
+            $appliedTaxesArray[] = $appliedTaxArray;
+        }
+
+        return $appliedTaxesArray;
+    }
+
+    /**
+     * Collect applied tax rates information on address level
+     *
+     * @param Address $address
+     * @param array $applied
+     * @param float $amount
+     * @param float $baseAmount
+     * @param float $rate
+     * @return void
+     */
+    protected function _saveAppliedTaxes(
+        Address $address,
+        $applied,
+        $amount,
+        $baseAmount,
+        $rate
+    ) {
+        $previouslyAppliedTaxes = $address->getAppliedTaxes();
+        $process = count($previouslyAppliedTaxes);
+
+        foreach ($applied as $row) {
+            if ($row['percent'] == 0) {
+                continue;
+            }
+            if (!isset($previouslyAppliedTaxes[$row['id']])) {
+                $row['process'] = $process;
+                $row['amount'] = 0;
+                $row['base_amount'] = 0;
+                $previouslyAppliedTaxes[$row['id']] = $row;
+            }
+
+            if (!is_null($row['percent'])) {
+                $row['percent'] = $row['percent'] ? $row['percent'] : 1;
+                $rate = $rate ? $rate : 1;
+
+                $appliedAmount = $amount / $rate * $row['percent'];
+                $baseAppliedAmount = $baseAmount / $rate * $row['percent'];
+            } else {
+                $appliedAmount = 0;
+                $baseAppliedAmount = 0;
+                foreach ($row['rates'] as $rate) {
+                    $appliedAmount += $rate['amount'];
+                    $baseAppliedAmount += $rate['base_amount'];
+                }
+            }
+
+            if ($appliedAmount || $previouslyAppliedTaxes[$row['id']]['amount']) {
+                $previouslyAppliedTaxes[$row['id']]['amount'] += $appliedAmount;
+                $previouslyAppliedTaxes[$row['id']]['base_amount'] += $baseAppliedAmount;
+            } else {
+                unset($previouslyAppliedTaxes[$row['id']]);
+            }
+        }
+        $address->setAppliedTaxes($previouslyAppliedTaxes);
+    }
+
+    /**
+     * Determine whether to include shipping in tax calculation
+     *
+     * @return bool
+     */
+    protected function includeShipping()
+    {
+        return false;
+    }
+
+    /**
+     * Determine whether to include item in tax calculation
+     *
+     * @return bool
+     */
+    protected function includeItems()
+    {
+        return false;
+    }
+
+    /**
+     * Determine whether to include item in tax calculation
+     *
+     * @return bool
+     */
+    protected function includeExtraTax()
+    {
+        return false;
+    }
+
+    /**
+     * Determine whether to save applied tax in address
+     *
+     * @return bool
+     */
+    protected function saveAppliedTaxes()
+    {
+        return false;
+    }
+}
diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/Shipping.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/Shipping.php
index cba13d0a9f95d5d3d7736dfa4c90fcc8f7f25e6b..ee8a2639c3c3377a92f8ffc1e4d6ee860ee9a083 100644
--- a/app/code/Magento/Tax/Model/Sales/Total/Quote/Shipping.php
+++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/Shipping.php
@@ -26,33 +26,43 @@ namespace Magento\Tax\Model\Sales\Total\Quote;
 use Magento\Sales\Model\Quote\Address;
 use Magento\Tax\Model\Calculation;
 
-class Shipping extends Tax
+class Shipping extends CommonTaxCollector
 {
     /**
-     * {@inheritdoc}
-     */
-    protected function includeShipping()
-    {
-        return true;
-    }
-    /**
-     * Override the behavior in Tax collector to not process extra subtotal amount to avoid double counting
+     * Collect tax totals for shipping. The result can be used to calculate discount on shipping
      *
-     * @return bool
+     * @param   Address $address
+     * @return  $this
      */
-    protected function processExtraSubtotalAmount()
+    public function collect(Address $address)
     {
-        return false;
-    }
+        parent::collect($address);
+        $items = $this->_getAddressItems($address);
+        if (!$items) {
+            return $this;
+        }
 
-    /**
-     * Override the behavior in Tax collector to return empty array
-     *
-     * @param Address $address
-     * @return array
-     */
-    public function fetch(Address $address)
-    {
-        return [];
+        //Add shipping
+        $shippingDataObject = $this->getShippingDataObject($address, false);
+        $baseShippingDataObject = $this->getShippingDataObject($address, true);
+        if ($shippingDataObject == null || $baseShippingDataObject == null) {
+            return $this;
+        }
+
+        $quoteDetails = $this->prepareQuoteDetails($address, [$shippingDataObject]);
+        $taxDetails = $this->taxCalculationService
+            ->calculateTax($quoteDetails, $address->getQuote()->getStore()->getStoreId());
+
+        $baseQuoteDetails = $this->prepareQuoteDetails($address, [$baseShippingDataObject]);
+        $baseTaxDetails = $this->taxCalculationService
+            ->calculateTax($baseQuoteDetails, $address->getQuote()->getStore()->getStoreId());
+
+        $this->processShippingTaxInfo(
+            $address,
+            $taxDetails->getItems()[self::ITEM_CODE_SHIPPING],
+            $baseTaxDetails->getItems()[self::ITEM_CODE_SHIPPING]
+        );
+
+        return $this;
     }
 }
diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/Subtotal.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/Subtotal.php
index 80eae0d9f88964c02d7a363a9b312efbc90f19a9..b8398e81bbcea70a2e6c2be1632bba1a2a6d0f0f 100644
--- a/app/code/Magento/Tax/Model/Sales/Total/Quote/Subtotal.php
+++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/Subtotal.php
@@ -31,37 +31,42 @@ use Magento\Sales\Model\Quote\Address;
 use Magento\Sales\Model\Quote\Item\AbstractItem;
 use Magento\Tax\Model\Calculation;
 
-class Subtotal extends Tax
+class Subtotal extends CommonTaxCollector
 {
     /**
-     * {@inheritdoc}
+     * Calculate tax on product items. The result will be used to determine shipping
+     * and discount later.
+     *
+     * @param   Address $address
+     * @return  $this
      */
-    protected function includeShipping()
+    public function collect(Address $address)
     {
-        return false;
-    }
+        parent::collect($address);
+        $items = $this->_getAddressItems($address);
+        if (!$items) {
+            return $this;
+        }
 
+        $priceIncludesTax = $this->_config->priceIncludesTax($this->_store);
 
-    /**
-     * Override the behavior in Tax collector to not process extra subtotal amount to avoid double counting
-     *
-     * @return bool
-     */
-    protected function processExtraSubtotalAmount()
-    {
-        $result = false;
-        return $result;
-    }
+        //Setup taxable items
+        $itemDataObjects = $this->mapItems($address, $priceIncludesTax, false);
+        $quoteDetails = $this->prepareQuoteDetails($address, $itemDataObjects);
+        $taxDetails = $this->taxCalculationService
+            ->calculateTax($quoteDetails, $address->getQuote()->getStore()->getStoreId());
 
-    /**
-     * Override the behavior in Tax collector to return empty array
-     *
-     * @param Address $address
-     * @return array
-     */
-    public function fetch(Address $address)
-    {
-        $result = [];
-        return $result;
+        $itemDataObjects = $this->mapItems($address, $priceIncludesTax, true);
+        $baseQuoteDetails = $this->prepareQuoteDetails($address, $itemDataObjects);
+        $baseTaxDetails = $this->taxCalculationService
+            ->calculateTax($baseQuoteDetails, $address->getQuote()->getStore()->getStoreId());
+
+        $itemsByType = $this->organizeItemTaxDetailsByType($taxDetails, $baseTaxDetails);
+
+        if (isset($itemsByType[self::ITEM_TYPE_PRODUCT])) {
+            $this->processProductItems($address, $itemsByType[self::ITEM_TYPE_PRODUCT]);
+        }
+
+        return $this;
     }
 }
diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php
index 776f3d03952ecb3264d8fa28b262d9e19fbd3a25..25a3529507b9c12bbdc8704ef802e13f2c751b9a 100644
--- a/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php
+++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php
@@ -32,25 +32,14 @@ use Magento\Customer\Service\V1\Data\AddressBuilder;
 use Magento\Tax\Service\V1\Data\QuoteDetailsBuilder;
 use Magento\Tax\Service\V1\Data\QuoteDetails\ItemBuilder;
 use Magento\Tax\Service\V1\Data\QuoteDetails\Item as ItemDataObject;
+use Magento\Tax\Service\V1\Data\TaxClassKey;
 use Magento\Tax\Service\V1\Data\TaxDetails;
 
 /**
  * Tax totals calculation model
  */
-class Tax extends AbstractTotal
+class Tax extends CommonTaxCollector
 {
-    /**#@+
-     * Constants defined for type of items
-     */
-    const SHIPPING_ITEM_TYPE = 'shipping';
-    const PRODUCT_ITEM_TYPE = 'product';
-    /**#@-*/
-
-    /**
-     * Constant for shipping item code
-     */
-    const SHIPPING_ITEM_CODE = 'shipping';
-
     /**
      * Static counter
      *
@@ -132,489 +121,171 @@ class Tax extends AbstractTotal
         if (!$items) {
             return $this;
         }
-        //Preparation for calling taxCalculationService with base currency
-        $quoteDetails = $this->prepareQuoteDetails($address, true);
 
-        $baseTaxDetailsBase = $this->taxCalculationService
-            ->calculateTax($quoteDetails, $address->getQuote()->getStore()->getStoreId());
+        $baseTaxDetails = $this->getQuoteTaxDetails($address, true);
+        $taxDetails = $this->getQuoteTaxDetails($address, false);
 
-        //Preparation for calling taxCalculationService with display currency
-        $quoteDetails = $this->prepareQuoteDetails($address, false);
+        //Populate address and items with tax calculation results
+        $itemsByType = $this->organizeItemTaxDetailsByType($taxDetails, $baseTaxDetails);
+        if (isset($itemsByType[self::ITEM_TYPE_PRODUCT])) {
+            $this->processProductItems($address, $itemsByType[self::ITEM_TYPE_PRODUCT]);
+        }
 
-        $taxDetails = $this->taxCalculationService
-            ->calculateTax($quoteDetails, $address->getQuote()->getStore()->getStoreId());
+        if (isset($itemsByType[self::ITEM_TYPE_SHIPPING])) {
+            $shippingTaxDetails = $itemsByType[self::ITEM_TYPE_SHIPPING][self::ITEM_CODE_SHIPPING][self::KEY_ITEM];
+            $baseShippingTaxDetails =
+                $itemsByType[self::ITEM_TYPE_SHIPPING][self::ITEM_CODE_SHIPPING][self::KEY_BASE_ITEM];
+            $this->processShippingTaxInfo($address, $shippingTaxDetails, $baseShippingTaxDetails);
+        }
 
+        //Process taxable items that are not product or shipping
+        $this->processExtraTaxables($address, $itemsByType);
 
-        //Populate address and items with tax calculation results
-        $this->updateTaxInfo($address, $taxDetails, $baseTaxDetailsBase);
-
-        if ($this->processExtraSubtotalAmount()) {
-            $address->addTotalAmount('tax', $address->getExtraTaxAmount());
-            $address->addBaseTotalAmount('tax', $address->getBaseExtraTaxAmount());
-            $address->addTotalAmount('subtotal', $address->getExtraSubtotalAmount());
-            $address->addBaseTotalAmount('subtotal', $address->getBaseExtraSubtotalAmount());
-            $address->setSubtotalInclTax(
-                $address->getSubtotalInclTax() + $address->getExtraSubtotalAmount() + $address->getExtraTaxAmount()
-            );
-            $address->setBaseSubtotalInclTax(
-                $address->getBaseSubtotalInclTax() +
-                $address->getBaseExtraSubtotalAmount() +
-                $address->getBaseExtraTaxAmount()
-            );
+        //Save applied taxes for each item and the quote in aggregation
+        $this->processAppliedTaxes($address, $itemsByType);
+
+        if ($this->includeExtraTax()) {
+            $this->_addAmount($address->getExtraTaxAmount());
+            $this->_addBaseAmount($address->getBaseExtraTaxAmount());
         }
+
         return $this;
     }
 
     /**
-     * Populate QuoteDetails object from Address object
+     * Call tax calculation service to get tax details on the quote and items
      *
      * @param Address $address
      * @param bool $useBaseCurrency
-     * @return \Magento\Tax\Service\V1\Data\QuoteDetails
+     * @return TaxDetails
      */
-    protected function prepareQuoteDetails(Address $address, $useBaseCurrency)
+    protected function getQuoteTaxDetails($address, $useBaseCurrency)
     {
-        $items = $this->_getAddressItems($address);
-        if (!count($items)) {
-            return $this->quoteDetailsBuilder->create();
-        }
-
-        $addressBuilder = $this->quoteDetailsBuilder->getAddressBuilder();
-
-        //Set billing address
-        $this->quoteDetailsBuilder->setBillingAddress(
-            $this->mapAddress($addressBuilder, $address->getQuote()->getBillingAddress())
-        );
-        //Set shipping address
-        $this->quoteDetailsBuilder->setShippingAddress(
-            $this->mapAddress($addressBuilder, $address)
-        );
-        //Set customer tax class
-        $this->quoteDetailsBuilder->setCustomerTaxClassId($address->getQuote()->getCustomerTaxClassId());
-        //Populate with items
+        //Setup taxable items
         $priceIncludesTax = $this->_config->priceIncludesTax($this->_store);
-        $itemBuilder = $this->quoteDetailsBuilder->getItemBuilder();
-        $itemDataObjects = [];
-        foreach ($items as $item) {
-            if ($item->getParentItem()) {
-                continue;
-            }
+        $itemDataObjects = $this->mapItems($address, $priceIncludesTax, $useBaseCurrency);
 
-            if ($item->getHasChildren() && $item->isChildrenCalculated()) {
-                $parentItemDataObject = $this->mapItem($itemBuilder, $item, $priceIncludesTax, $useBaseCurrency);
-                $itemDataObjects[] = $parentItemDataObject;
-                foreach ($item->getChildren() as $child) {
-                    $childItemDataObject = $this->mapItem(
-                        $itemBuilder,
-                        $child,
-                        $priceIncludesTax,
-                        $useBaseCurrency,
-                        $parentItemDataObject->getCode()
-                    );
-                    $itemDataObjects[] = $childItemDataObject;
-                }
-            } else {
-                $itemDataObject = $this->mapItem($itemBuilder, $item, $priceIncludesTax, $useBaseCurrency);
-                $itemDataObjects[] = $itemDataObject;
-            }
+        //Add shipping
+        $shippingDataObject = $this->getShippingDataObject($address, $useBaseCurrency);
+        if ($shippingDataObject != null) {
+            $itemDataObjects[] = $shippingDataObject;
         }
 
-        if ($this->includeShipping()) {
-            //Add shipping as an item
-            if (!$address->getShippingTaxCalculationAmount() || $address->getShippingTaxCalculationAmount() <= 0) {
-                //Save the original shipping amount because shipping amount will be overridden
-                //with shipping amount excluding tax
-                $address->setShippingTaxCalculationAmount($address->getShippingAmount());
-                $address->setBaseShippingTaxCalculationAmount($address->getBaseShippingAmount());
-            }
-            if ($address->getShippingTaxCalculationAmount() > 0) {
-                $itemBuilder->setType(self::SHIPPING_ITEM_TYPE);
-                $itemBuilder->setCode(self::SHIPPING_ITEM_CODE);
-                $itemBuilder->setQuantity(1);
-                if ($useBaseCurrency) {
-                    $itemBuilder->setUnitPrice($address->getBaseShippingTaxCalculationAmount());
-                } else {
-                    $itemBuilder->setUnitPrice($address->getShippingTaxCalculationAmount());
-                }
-                if ($address->getShippingDiscountAmount()) {
-                    if ($useBaseCurrency) {
-                        $itemBuilder->setDiscountAmount($address->getBaseShippingDiscountAmount());
-                    } else {
-                        $itemBuilder->setDiscountAmount($address->getShippingDiscountAmount());
-                    }
-                }
-                $itemBuilder->setTaxClassId($this->_config->getShippingTaxClass($this->_store));
-                $itemBuilder->setTaxIncluded($this->_config->shippingPriceIncludesTax($this->_store));
-                $itemDataObjects[] = $itemBuilder->create();
-            }
+        //process extra taxable items associated only with quote
+        $quoteExtraTaxables = $this->mapQuoteExtraTaxables(
+            $this->quoteDetailsBuilder->getItemBuilder(),
+            $address,
+            $useBaseCurrency
+        );
+        if (!empty($quoteExtraTaxables)) {
+            $itemDataObjects = array_merge($itemDataObjects, $quoteExtraTaxables);
         }
-        $this->quoteDetailsBuilder->setItems($itemDataObjects);
 
-        $quoteDetails = $this->quoteDetailsBuilder->create();
-        return $quoteDetails;
-    }
+        //Preparation for calling taxCalculationService
+        $quoteDetails = $this->prepareQuoteDetails($address, $itemDataObjects);
 
-    /**
-     * Map Address to Address data object
-     *
-     * @param AddressBuilder $addressBuilder
-     * @param Address $address
-     * @return \Magento\Customer\Service\V1\Data\Address
-     */
-    protected function mapAddress(AddressBuilder $addressBuilder, Address $address)
-    {
-        $addressBuilder->setCountryId($address->getCountryId());
-        $addressBuilder->setRegion(
-            $addressBuilder->getRegionBuilder()
-                ->setRegionId($address->getRegionId())
-                ->create()
-        );
-        $addressBuilder->setPostcode($address->getPostcode());
-        $addressBuilder->setCity($address->getCity());
-        $addressBuilder->setStreet($address->getStreet());
+        $taxDetails = $this->taxCalculationService
+            ->calculateTax($quoteDetails, $address->getQuote()->getStore()->getStoreId());
 
-        return $addressBuilder->create();
+        return $taxDetails;
     }
 
+
     /**
-     * Map an item to item data object
+     * Map extra taxables associated with quote
      *
      * @param ItemBuilder $itemBuilder
-     * @param AbstractItem $item
-     * @param bool $priceIncludesTax
+     * @param Address $address
      * @param bool $useBaseCurrency
-     * @param string $parentCode
-     * @return ItemDataObject
+     * @return ItemDataObject[]
      */
-    protected function mapItem(
+    public function mapQuoteExtraTaxables(
         ItemBuilder $itemBuilder,
-        AbstractItem $item,
-        $priceIncludesTax,
-        $useBaseCurrency,
-        $parentCode = null
+        Address $address,
+        $useBaseCurrency
     ) {
-        if (!$item->getSequence()) {
-            $sequence = 'sequence-' . $this->getNextIncrement();
-            $item->setSequence($sequence);
-        }
-        $itemBuilder->setCode($item->getSequence());
-        $itemBuilder->setQuantity($item->getQty());
-        $itemBuilder->setTaxClassId($item->getProduct()->getTaxClassId());
-
-        $itemBuilder->setTaxIncluded($priceIncludesTax);
-        $itemBuilder->setType('product'); //TODO: find a place to define constants
-
-        if ($item->getParentItem()) {
-            $itemBuilder->setParentCode($item->getParentItem()->getId());
+        $itemDataObjects = [];
+        $extraTaxables = $address->getAssociatedTaxables();
+        if (!$extraTaxables) {
+            return [];
         }
 
-        if ($useBaseCurrency) {
-            if (!$item->getBaseTaxCalculationPrice()) {
-                $item->setBaseTaxCalculationPrice($item->getBaseCalculationPriceOriginal());
-            }
-            $itemBuilder->setUnitPrice($item->getBaseTaxCalculationPrice());
-            $itemBuilder->setDiscountAmount($item->getBaseDiscountAmount());
-        } else {
-            if (!$item->getTaxCalculationPrice()) {
-                $item->setTaxCalculationPrice($item->getCalculationPriceOriginal());
+        foreach ($extraTaxables as $extraTaxable) {
+            $itemBuilder->setCode($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_CODE]);
+            $itemBuilder->setType($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_TYPE]);
+            $itemBuilder->setQuantity($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_QUANTITY]);
+            $itemBuilder->setTaxClassKey(
+                $itemBuilder->getTaxClassKeyBuilder()
+                    ->setType(TaxClassKey::TYPE_ID)
+                    ->setValue($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_TAX_CLASS_ID])
+                    ->create()
+            );
+            if ($useBaseCurrency) {
+                $unitPrice = $extraTaxable[self::KEY_ASSOCIATED_TAXABLE_BASE_UNIT_PRICE];
+            } else {
+                $unitPrice = $extraTaxable[self::KEY_ASSOCIATED_TAXABLE_UNIT_PRICE];
             }
-            $itemBuilder->setUnitPrice($item->getTaxCalculationPrice());
-            $itemBuilder->setDiscountAmount($item->getDiscountAmount());
+            $itemBuilder->setUnitPrice($unitPrice);
+            $itemBuilder->setTaxIncluded($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_PRICE_INCLUDES_TAX]);
+            $itemBuilder->setAssociatedItemCode($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_ASSOCIATION_ITEM_CODE]);
+            $itemDataObjects[] = $itemBuilder->create();
         }
 
-        $itemBuilder->setParentCode($parentCode);
-
-        return $itemBuilder->create();
+        return $itemDataObjects;
     }
 
     /**
-     * Increment and return static counter
-     *
-     * @return int
-     */
-    protected function getNextIncrement()
-    {
-        return ++self::$counter;
-    }
-
-    /**
-     * Update item tax and prices from item tax details object from tax calculation service
+     * Process everything other than product or shipping, save the result in quote
      *
      * @param Address $address
-     * @param TaxDetails $taxDetails
-     * @param TaxDetails $baseTaxDetails
+     * @param array $itemsByType
      * @return $this
      */
-    protected function updateTaxInfo(Address $address, TaxDetails $taxDetails, TaxDetails $baseTaxDetails)
+    protected function processExtraTaxables(Address $address, Array $itemsByType)
     {
-        $address->setAppliedTaxes([]);
-        /** @var \Magento\Tax\Service\V1\Data\TaxDetails\Item[] $keyedItems */
-        $keyedItems = [];
-        foreach ($taxDetails->getItems() as $item) {
-            $keyedItems[$item->getCode()] = $item;
-        }
-        /** @var \Magento\Tax\Service\V1\Data\TaxDetails\Item[] $baseKeyedItems */
-        $baseKeyedItems = [];
-        foreach ($baseTaxDetails->getItems() as $item) {
-            $baseKeyedItems[$item->getCode()] = $item;
-        }
-
-        $appliedTaxesByItem = [];
-
-        /** @var AbstractItem[] $keyedAddressItems */
-        $keyedAddressItems = [];
-        foreach ($this->_getAddressItems($address) as $addressItem) {
-            $keyedAddressItems[$addressItem->getSequence()] = $addressItem;
-        }
-
-        $subtotal = $baseSubtotal = 0;
-        $hiddenTax = $baseHiddenTax = 0;
-        $tax = $baseTax = 0;
-        $subtotalInclTax = $baseSubtotalInclTax = 0;
-
-        foreach ($keyedItems as $code => $itemTaxDetails) {
-            $baseItemTaxDetails = $baseKeyedItems[$code];
-            $type = $itemTaxDetails->getType();
-            if ($type == self::PRODUCT_ITEM_TYPE) {
-                $quoteItem = $keyedAddressItems[$code];
-                $this->updateItemTaxInfo($quoteItem, $itemTaxDetails, $baseItemTaxDetails);
-
-                if ($quoteItem->getHasChildren() && $quoteItem->isChildrenCalculated()) {
-                    //avoid double counting
-                    continue;
+        $extraTaxableDetails = [];
+        foreach ($itemsByType as $itemType => $itemTaxDetails) {
+            if ($itemType != self::ITEM_TYPE_PRODUCT and $itemType != self::ITEM_TYPE_SHIPPING) {
+                foreach ($itemTaxDetails as $itemCode => $itemTaxDetail) {
+                    /** @var ItemTaxDetails $taxDetails */
+                    $taxDetails = $itemTaxDetail[self::KEY_ITEM];
+                    /** @var ItemTaxDetails $baseTaxDetails */
+                    $baseTaxDetails = $itemTaxDetail[self::KEY_BASE_ITEM];
+
+                    $appliedTaxes = $taxDetails->getAppliedTaxes();
+                    $baseAppliedTaxes = $baseTaxDetails->getAppliedTaxes();
+
+                    $associatedItemCode = $taxDetails->getAssociatedItemCode();
+
+                    $appliedTaxesArray = $this->convertAppliedTaxes($appliedTaxes, $baseAppliedTaxes);
+                    $extraTaxableDetails[$itemType][$associatedItemCode][] = [
+                        self::KEY_TAX_DETAILS_TYPE => $taxDetails->getType(),
+                        self::KEY_TAX_DETAILS_CODE => $taxDetails->getCode(),
+                        self::KEY_TAX_DETAILS_PRICE_EXCL_TAX => $taxDetails->getPrice(),
+                        self::KEY_TAX_DETAILS_PRICE_INCL_TAX => $taxDetails->getPriceInclTax(),
+                        self::KEY_TAX_DETAILS_BASE_PRICE_EXCL_TAX => $baseTaxDetails->getPrice(),
+                        self::KEY_TAX_DETAILS_BASE_PRICE_INCL_TAX => $baseTaxDetails->getPriceInclTax(),
+                        self::KEY_TAX_DETAILS_ROW_TOTAL => $taxDetails->getRowTotal(),
+                        self::KEY_TAX_DETAILS_ROW_TOTAL_INCL_TAX => $taxDetails->getRowTotalInclTax(),
+                        self::KEY_TAX_DETAILS_BASE_ROW_TOTAL => $baseTaxDetails->getRowTotal(),
+                        self::KEY_TAX_DETAILS_BASE_ROW_TOTAL_INCL_TAX => $baseTaxDetails->getRowTotalInclTax(),
+                        self::KEY_TAX_DETAILS_TAX_PERCENT => $taxDetails->getTaxPercent(),
+                        self::KEY_TAX_DETAILS_ROW_TAX => $taxDetails->getRowTax(),
+                        self::KEY_TAX_DETAILS_BASE_ROW_TAX => $baseTaxDetails->getRowTax(),
+                        self::KEY_TAX_DETAILS_APPLIED_TAXES => $appliedTaxesArray,
+                    ];
+
+                    $address->addTotalAmount('tax', $taxDetails->getRowTax());
+                    $address->addBaseTotalAmount('tax', $baseTaxDetails->getRowTax());
+                    //TODO: save applied taxes for the item
                 }
-                $subtotal += $itemTaxDetails->getRowTotal();
-                $baseSubtotal += $baseItemTaxDetails->getRowTotal();
-                $hiddenTax += $itemTaxDetails->getDiscountTaxCompensationAmount();
-                $baseHiddenTax += $baseItemTaxDetails->getDiscountTaxCompensationAmount();
-                $tax += $itemTaxDetails->getRowTax();
-                $baseTax += $baseItemTaxDetails->getRowTax();
-                $subtotalInclTax += $itemTaxDetails->getRowTotalInclTax();
-                $baseSubtotalInclTax += $baseItemTaxDetails->getRowTotalInclTax();
-
-                $appliedTaxes = $itemTaxDetails->getAppliedTaxes();
-                $baseAppliedTaxes = $baseItemTaxDetails->getAppliedTaxes();
-                $appliedTaxesArray = $this->convertAppliedTaxes($appliedTaxes, $baseAppliedTaxes);
-
-                foreach ($appliedTaxesArray as $appliedTaxArray) {
-                    $this->_saveAppliedTaxes(
-                        $address,
-                        [$appliedTaxArray],
-                        $appliedTaxArray['amount'],
-                        $appliedTaxArray['base_amount'],
-                        $appliedTaxArray['percent']
-                    );
-                }
-
-                $appliedTaxesByItem[$quoteItem->getId()] = $appliedTaxesArray;
-                //Set applied tax for item
-                $quoteItem->setAppliedTaxes($appliedTaxesArray);
             }
-            $address->getQuote()->setTaxesForItems($appliedTaxesByItem);
-        }
-
-        // Set item subtotals
-        $address->setTotalAmount('subtotal', $subtotal);
-        $address->setBaseTotalAmount('subtotal', $baseSubtotal);
-
-        $address->setSubtotalInclTax($subtotalInclTax);
-        $address->setBaseSubtotalInclTax($baseSubtotalInclTax);
-        $address->setTotalAmount('hidden_tax', $hiddenTax);
-        $address->setBaseTotalAmount('hidden_tax', $baseHiddenTax);
-
-        //Set shipping tax
-        if (isset($keyedItems[self::SHIPPING_ITEM_CODE]) && isset($baseKeyedItems[self::SHIPPING_ITEM_CODE])) {
-            $shippingItem = $keyedItems[self::SHIPPING_ITEM_CODE];
-            $baseShippingItem = $baseKeyedItems[self::SHIPPING_ITEM_CODE];
-
-            $this->updateShippingTaxInfo($address, $shippingItem, $baseShippingItem);
-
-            $tax += $shippingItem->getRowTax();
-            $baseTax += $baseShippingItem->getRowTax();
-        }
-
-        $address->setTotalAmount('tax', $tax);
-        $address->setBaseTotalAmount('tax', $baseTax);
-
-        return $this;
-    }
-
-    /**
-     * Update tax related fields for quote item
-     *
-     * @param AbstractItem $quoteItem
-     * @param \Magento\Tax\Service\V1\Data\TaxDetails\Item $itemTaxDetails
-     * @param \Magento\Tax\Service\V1\Data\TaxDetails\Item $baseItemTaxDetails
-     * @return $this
-     */
-    protected function updateItemTaxInfo($quoteItem, $itemTaxDetails, $baseItemTaxDetails)
-    {
-        //The price should be base price
-        $quoteItem->setPrice($baseItemTaxDetails->getPrice());
-        $quoteItem->setConvertedPrice($itemTaxDetails->getPrice());
-        $quoteItem->setPriceInclTax($itemTaxDetails->getPriceInclTax());
-        $quoteItem->setRowTotal($itemTaxDetails->getRowTotal());
-        $quoteItem->setRowTotalInclTax($itemTaxDetails->getRowTotalInclTax());
-        $quoteItem->setTaxAmount($itemTaxDetails->getRowTax());
-        $quoteItem->setTaxPercent($itemTaxDetails->getTaxPercent());
-        $quoteItem->setHiddenTaxAmount($itemTaxDetails->getDiscountTaxCompensationAmount());
-
-        $quoteItem->setBasePrice($baseItemTaxDetails->getPrice());
-        $quoteItem->setBasePriceInclTax($baseItemTaxDetails->getPriceInclTax());
-        $quoteItem->setBaseRowTotal($baseItemTaxDetails->getRowTotal());
-        $quoteItem->setBaseRowTotalInclTax($baseItemTaxDetails->getRowTotalInclTax());
-        $quoteItem->setBaseTaxAmount($baseItemTaxDetails->getRowTax());
-        $quoteItem->setTaxPercent($baseItemTaxDetails->getTaxPercent());
-        $quoteItem->setBaseHiddenTaxAmount($baseItemTaxDetails->getDiscountTaxCompensationAmount());
-
-        //Set discount calculation price, this may be needed by discount collector
-        if ($this->_config->discountTax($this->_store)) {
-            $quoteItem->setDiscountCalculationPrice($itemTaxDetails->getPriceInclTax());
-            $quoteItem->setBaseDiscountCalculationPrice($baseItemTaxDetails->getPriceInclTax());
-        } else {
-            $quoteItem->setDiscountCalculationPrice($itemTaxDetails->getPrice());
-            $quoteItem->setBaseDiscountCalculationPrice($baseItemTaxDetails->getPrice());
-
-        }
-        return $this;
-    }
-
-    /**
-     * Update tax related fields for shipping
-     *
-     * @param Address $address
-     * @param \Magento\Tax\Service\V1\Data\TaxDetails\Item $shippingTaxDetails
-     * @param \Magento\Tax\Service\V1\Data\TaxDetails\Item $baseShippingTaxDetails
-     * @return $this
-     */
-    protected function updateShippingTaxInfo(Address $address, $shippingTaxDetails, $baseShippingTaxDetails)
-    {
-        $address->setTotalAmount('shipping', $shippingTaxDetails->getRowTotal());
-        $address->setBaseTotalAmount('shipping', $baseShippingTaxDetails->getRowTotal());
-        $address->setShippingTaxAmount($shippingTaxDetails->getRowTax());
-        $address->setBaseShippingTaxAmount($baseShippingTaxDetails->getRowTax());
-        $address->setTotalAmount('shipping_hidden_tax', $shippingTaxDetails->getDiscountTaxCompensationAmount());
-        $address->setBaseTotalAmount('shipping_hidden_tax', $baseShippingTaxDetails->getDiscountTaxCompensationAmount());
-
-        $address->setShippingInclTax($shippingTaxDetails->getRowTotalInclTax());
-        $address->setBaseShippingInclTax($baseShippingTaxDetails->getRowTotalInclTax());
-
-        if ($this->_config->discountTax($this->_store)) {
-            $address->setShippingAmountForDiscount($shippingTaxDetails->getRowTotalInclTax());
-            $address->setBaseShippingAmountForDiscount($baseShippingTaxDetails->getRowTotalInclTax());
         }
 
-        //Add taxes applied to shipping to applied taxes
-        $appliedTaxes = $shippingTaxDetails->getAppliedTaxes();
-        $baseAppliedTaxes = $baseShippingTaxDetails->getAppliedTaxes();
-        $appliedTaxesArray = $this->convertAppliedTaxes($appliedTaxes, $baseAppliedTaxes);
-        $this->_saveAppliedTaxes(
-            $address,
-            $appliedTaxesArray,
-            $shippingTaxDetails->getRowTax(),
-            $baseShippingTaxDetails->getRowTax(),
-            $shippingTaxDetails->getTaxPercent()
-        );
-
+        $address->setExtraTaxableDetails($extraTaxableDetails);
         return $this;
     }
 
-    /**
-     * Convert appliedTax data object from tax calculation service to internal array format
-     *
-     * @param \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[] $appliedTaxes
-     * @param \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[] $baseAppliedTaxes
-     * @return array
-     */
-    protected function convertAppliedTaxes($appliedTaxes, $baseAppliedTaxes)
-    {
-        $appliedTaxesArray = [];
-
-        if (!$appliedTaxes || !$baseAppliedTaxes) {
-            return $appliedTaxesArray;
-        }
-
-        foreach ($appliedTaxes as $taxId => $appliedTax) {
-            $baseAppliedTax = $baseAppliedTaxes[$taxId];
-            $rateDataObjects = $appliedTax->getRates();
-
-            $rates = [];
-            foreach ($rateDataObjects as $rateDataObject) {
-                $rates[] = [
-                    'percent' => $rateDataObject->getPercent(),
-                    'code' => $rateDataObject->getCode(),
-                    'title' => $rateDataObject->getTitle(),
-                ];
-            }
-
-            $appliedTaxesArray[] = [
-                'amount' => $appliedTax->getAmount(),
-                'base_amount' => $baseAppliedTax->getAmount(),
-                'percent' => $appliedTax->getPercent(),
-                'id' => $appliedTax->getTaxRateKey(),
-                'rates' => $rates,
-            ];
-        }
-
-        return $appliedTaxesArray;
-    }
-
-    /**
-     * Collect applied tax rates information on address level
-     *
-     * @param Address $address
-     * @param array $applied
-     * @param float $amount
-     * @param float $baseAmount
-     * @param float $rate
-     * @return void
-     */
-    protected function _saveAppliedTaxes(
-        Address $address,
-        $applied,
-        $amount,
-        $baseAmount,
-        $rate
-    ) {
-        $previouslyAppliedTaxes = $address->getAppliedTaxes();
-        $process = count($previouslyAppliedTaxes);
-
-        foreach ($applied as $row) {
-            if ($row['percent'] == 0) {
-                continue;
-            }
-            if (!isset($previouslyAppliedTaxes[$row['id']])) {
-                $row['process'] = $process;
-                $row['amount'] = 0;
-                $row['base_amount'] = 0;
-                $previouslyAppliedTaxes[$row['id']] = $row;
-            }
-
-            if (!is_null($row['percent'])) {
-                $row['percent'] = $row['percent'] ? $row['percent'] : 1;
-                $rate = $rate ? $rate : 1;
-
-                $appliedAmount = $amount / $rate * $row['percent'];
-                $baseAppliedAmount = $baseAmount / $rate * $row['percent'];
-            } else {
-                $appliedAmount = 0;
-                $baseAppliedAmount = 0;
-                foreach ($row['rates'] as $rate) {
-                    $appliedAmount += $rate['amount'];
-                    $baseAppliedAmount += $rate['base_amount'];
-                }
-            }
-
-            if ($appliedAmount || $previouslyAppliedTaxes[$row['id']]['amount']) {
-                $previouslyAppliedTaxes[$row['id']]['amount'] += $appliedAmount;
-                $previouslyAppliedTaxes[$row['id']]['base_amount'] += $baseAppliedAmount;
-            } else {
-                unset($previouslyAppliedTaxes[$row['id']]);
-            }
-        }
-        $address->setAppliedTaxes($previouslyAppliedTaxes);
-    }
-
     /**
      * Add tax totals information to address object
      *
@@ -707,24 +378,4 @@ class Tax extends AbstractTotal
     {
         return __('Tax');
     }
-
-    /**
-     * Determine whether to include shipping in tax calculation
-     *
-     * @return bool
-     */
-    protected function includeShipping()
-    {
-        return true;
-    }
-
-    /**
-     * Return a flag to indicate whether to process extra subtotal field in the quote
-     *
-     * @return bool
-     */
-    protected function processExtraSubtotalAmount()
-    {
-        return true;
-    }
 }
diff --git a/app/code/Magento/Tax/Model/TaxClass/Source/Product.php b/app/code/Magento/Tax/Model/TaxClass/Source/Product.php
index d4d7c9ff1e871e051587bccd9d607d4a590ae6d3..c102950e4a0d4bb5137b35434c2a37cfb49c723f 100644
--- a/app/code/Magento/Tax/Model/TaxClass/Source/Product.php
+++ b/app/code/Magento/Tax/Model/TaxClass/Source/Product.php
@@ -24,6 +24,7 @@
 
 namespace Magento\Tax\Model\TaxClass\Source;
 
+use Magento\Framework\DB\Ddl\Table;
 use Magento\Tax\Service\V1\Data\TaxClass;
 
 /**
@@ -135,16 +136,20 @@ class Product extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
      *
      * @return array
      */
-    public function getFlatColums()
+    public function getFlatColumns()
     {
         $attributeCode = $this->getAttribute()->getAttributeCode();
-        $column = array('unsigned' => true, 'default' => null, 'extra' => null);
 
-        $column['type'] = \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER;
-        $column['nullable'] = true;
-        $column['comment'] = $attributeCode . ' tax column';
-
-        return array($attributeCode => $column);
+        return [
+            $attributeCode => [
+                'unsigned' => true,
+                'default' => null,
+                'extra' => null,
+                'type' => Table::TYPE_INTEGER,
+                'nullable' => true,
+                'comment' => $attributeCode . ' tax column',
+            ],
+        ];
     }
 
     /**
diff --git a/app/code/Magento/Tax/Pricing/Price/Plugin/AttributePrice.php b/app/code/Magento/Tax/Pricing/Price/Plugin/AttributePrice.php
index d5f511d5a4207cec1db555fd88e96ec55b4f7e96..6a9a0677a47a65424604a7507a998714a9cd5a14 100644
--- a/app/code/Magento/Tax/Pricing/Price/Plugin/AttributePrice.php
+++ b/app/code/Magento/Tax/Pricing/Price/Plugin/AttributePrice.php
@@ -34,20 +34,20 @@ class AttributePrice
     protected $taxHelper;
 
     /**
-     * @var \Magento\Tax\Model\Calculation
+     * @var \Magento\Tax\Service\V1\TaxCalculationServiceInterface
      */
-    protected $calculation;
+    protected $taxCalculationService;
 
     /**
      * @param \Magento\Tax\Helper\Data $helper
-     * @param \Magento\Tax\Model\Calculation $calculation
+     * @param \Magento\Tax\Service\V1\TaxCalculationServiceInterface $taxCalculationService
      */
     public function __construct(
         \Magento\Tax\Helper\Data $helper,
-        \Magento\Tax\Model\Calculation $calculation
+        \Magento\Tax\Service\V1\TaxCalculationServiceInterface $taxCalculationService
     ) {
         $this->taxHelper = $helper;
-        $this->calculation = $calculation;
+        $this->taxCalculationService = $taxCalculationService;
     }
 
     /**
@@ -65,10 +65,16 @@ class AttributePrice
 
         $productClassId = $product->getTaxClassId();
 
-        $defaultValue = $this->applyRate($productClassId, false, false, false, $result['customerId']);
+        $defaultValue = $this->taxCalculationService->getDefaultCalculatedRate(
+            $productClassId,
+            $result['customerId']
+        );
         $result['defaultTax'] = $defaultValue + $result['defaultTax'];
 
-        $currentTax = $this->applyRate($productClassId, null, null, null, $result['customerId']);
+        $currentTax = $this->taxCalculationService->getCalculatedRate(
+            $productClassId,
+            $result['customerId']
+        );
         $result['currentTax'] = $currentTax + $result['currentTax'];
 
         $adjustment = $product->getPriceInfo()->getAdjustment(\Magento\Tax\Pricing\Adjustment::ADJUSTMENT_CODE);
@@ -78,32 +84,4 @@ class AttributePrice
         $result['showBothPrices'] = $this->taxHelper->displayBothPrices();
         return $result;
     }
-
-    /**
-     * Apply Tax Rate
-     *
-     * @param int $classId
-     * @param null $shippingAddress
-     * @param null $billingAddress
-     * @param null $customerTaxClass
-     * @param int|null $customerId
-     * @return float
-     */
-    protected function applyRate(
-        $classId,
-        $shippingAddress = null,
-        $billingAddress = null,
-        $customerTaxClass = null,
-        $customerId = null
-    ) {
-        $rateRequest = $this->calculation->getRateRequest(
-            $shippingAddress,
-            $billingAddress,
-            $customerTaxClass,
-            null,
-            $customerId
-        );
-        $rateRequest->setProductClassId($classId);
-        return $this->calculation->getRate($rateRequest);
-    }
 }
diff --git a/app/code/Magento/Tax/Service/V1/Collection/TaxRuleCollection.php b/app/code/Magento/Tax/Service/V1/Collection/TaxRuleCollection.php
index 384b30432f8388bf588bf33877aa0a7e03fe3160..46aa4d16183cc2e1e56a50a81b81b5baaf627758 100644
--- a/app/code/Magento/Tax/Service/V1/Collection/TaxRuleCollection.php
+++ b/app/code/Magento/Tax/Service/V1/Collection/TaxRuleCollection.php
@@ -99,7 +99,7 @@ class TaxRuleCollection extends AbstractServiceCollection
         /* should cast to string so that some optional fields won't be null on the collection grid pages */
         $collectionItem->setPriority((string)$taxRule->getPriority());
         $collectionItem->setPosition((string)$taxRule->getSortOrder());
-        $collectionItem->setCalculateSubtotal((string)$taxRule->getCalculateSubtotal());
+        $collectionItem->setCalculateSubtotal($taxRule->getCalculateSubtotal() ? '1' : '0');
         $collectionItem->setCustomerTaxClasses($taxRule->getCustomerTaxClassIds());
         $collectionItem->setProductTaxClasses($taxRule->getProductTaxClassIds());
         $collectionItem->setTaxRates($taxRule->getTaxRateIds());
diff --git a/app/code/Magento/Tax/Service/V1/Data/QuoteDetails.php b/app/code/Magento/Tax/Service/V1/Data/QuoteDetails.php
index 1411a71a06cd09626ae800b434e680741a849aea..4a928878af1f3328c1e6fdfcd848f6759c93b42e 100644
--- a/app/code/Magento/Tax/Service/V1/Data/QuoteDetails.php
+++ b/app/code/Magento/Tax/Service/V1/Data/QuoteDetails.php
@@ -33,7 +33,7 @@ class QuoteDetails extends \Magento\Framework\Service\Data\AbstractObject
 
     const KEY_SHIPPING_ADDRESS = 'shipping_address';
 
-    const KEY_CUSTOMER_TAX_CLASS_ID = 'customer_tax_class_id';
+    const KEY_CUSTOMER_TAX_CLASS_KEY = 'customer_tax_class_key';
 
     const KEY_ITEMS = 'items';
 
@@ -61,19 +61,19 @@ class QuoteDetails extends \Magento\Framework\Service\Data\AbstractObject
     }
 
     /**
-     * Get customer tax class id
+     * Get customer tax class key
      *
-     * @return int|null
+     * @return \Magento\Tax\Service\V1\Data\TaxClassKey|null
      */
-    public function getCustomerTaxClassId()
+    public function getCustomerTaxClassKey()
     {
-        return $this->_get(self::KEY_CUSTOMER_TAX_CLASS_ID);
+        return $this->_get(self::KEY_CUSTOMER_TAX_CLASS_KEY);
     }
 
     /**
      * Get customer id
      *
-     * @return id|null
+     * @return int|null
      */
     public function getCustomerId()
     {
diff --git a/app/code/Magento/Tax/Service/V1/Data/QuoteDetails/Item.php b/app/code/Magento/Tax/Service/V1/Data/QuoteDetails/Item.php
index 7be400b173873f59b8129f738d67571d6f93010c..b8c507161af9a81b4bf95284948fbec02c12bddf 100644
--- a/app/code/Magento/Tax/Service/V1/Data/QuoteDetails/Item.php
+++ b/app/code/Magento/Tax/Service/V1/Data/QuoteDetails/Item.php
@@ -32,7 +32,7 @@ class Item extends \Magento\Framework\Service\Data\AbstractObject
 
     const KEY_TYPE = 'type';
 
-    const KEY_TAX_CLASS_ID = 'tax_class_id';
+    const KEY_TAX_CLASS_KEY = 'tax_class_key';
 
     const KEY_UNIT_PRICE = 'unit_price';
 
@@ -45,6 +45,8 @@ class Item extends \Magento\Framework\Service\Data\AbstractObject
     const KEY_DISCOUNT_AMOUNT = 'discount_amount';
 
     const KEY_PARENT_CODE = 'parent_code';
+
+    const KEY_ASSOCIATED_ITEM_CODE = 'association_code';
     /**#@-*/
 
     /**
@@ -68,13 +70,13 @@ class Item extends \Magento\Framework\Service\Data\AbstractObject
     }
 
     /**
-     * Get tax class id
+     * Get tax class key
      *
-     * @return int
+     * @return \Magento\Tax\Service\V1\Data\TaxClassKey
      */
-    public function getTaxClassId()
+    public function getTaxClassKey()
     {
-        return $this->_get(self::KEY_TAX_CLASS_ID);
+        return $this->_get(self::KEY_TAX_CLASS_KEY);
     }
 
     /**
@@ -136,4 +138,14 @@ class Item extends \Magento\Framework\Service\Data\AbstractObject
     {
         return $this->_get(self::KEY_PARENT_CODE);
     }
+
+    /**
+     * Get associated item code if this item is associated with another item, null otherwise
+     *
+     * @return mixed|null
+     */
+    public function getAssociatedItemCode()
+    {
+        return $this->_get(self::KEY_ASSOCIATED_ITEM_CODE);
+    }
 }
diff --git a/app/code/Magento/Tax/Service/V1/Data/QuoteDetails/ItemBuilder.php b/app/code/Magento/Tax/Service/V1/Data/QuoteDetails/ItemBuilder.php
index 0b94e9246afe5b43053cc6e8e3e6254aadc83187..44bb07e2157716a9f61aac18ccc9af6e416257b0 100644
--- a/app/code/Magento/Tax/Service/V1/Data/QuoteDetails/ItemBuilder.php
+++ b/app/code/Magento/Tax/Service/V1/Data/QuoteDetails/ItemBuilder.php
@@ -30,6 +30,37 @@ namespace Magento\Tax\Service\V1\Data\QuoteDetails;
  */
 class ItemBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
 {
+    /**
+     * TaxClassKey data object builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\TaxClassKeyBuilder
+     */
+    protected $taxClassKeyBuilder;
+
+    /**
+     * Initialize dependencies
+     *
+     * @param \Magento\Framework\Service\Data\ObjectFactory $objectFactory
+     * @param \Magento\Tax\Service\V1\Data\TaxClassKeyBuilder $taxClassKeyBuilder
+     */
+    public function __construct(
+        \Magento\Framework\Service\Data\ObjectFactory $objectFactory,
+        \Magento\Tax\Service\V1\Data\TaxClassKeyBuilder $taxClassKeyBuilder
+    ) {
+        parent::__construct($objectFactory);
+        $this->taxClassKeyBuilder = $taxClassKeyBuilder;
+    }
+
+    /**
+     * Get tax class key builder
+     *
+     * @return \Magento\Tax\Service\V1\Data\TaxClassKeyBuilder
+     */
+    public function getTaxClassKeyBuilder()
+    {
+        return $this->taxClassKeyBuilder;
+    }
+
     /**
      * Set code (sku or shipping code)
      *
@@ -53,14 +84,14 @@ class ItemBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
     }
 
     /**
-     * Set tax class id
+     * Set tax class key
      *
-     * @param int $taxClassId
+     * @param \Magento\Tax\Service\V1\Data\TaxClassKey $taxClassKey
      * @return $this
      */
-    public function setTaxClassId($taxClassId)
+    public function setTaxClassKey($taxClassKey)
     {
-        return $this->_set(Item::KEY_TAX_CLASS_ID, $taxClassId);
+        return $this->_set(Item::KEY_TAX_CLASS_KEY, $taxClassKey);
     }
 
     /**
@@ -128,4 +159,29 @@ class ItemBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
     {
         return $this->_set(Item::KEY_PARENT_CODE, $code);
     }
+
+    /**
+     * Set associated item code
+     *
+     * @param string $code
+     * @return $this
+     */
+    public function setAssociatedItemCode($code)
+    {
+        return $this->_set(Item::KEY_ASSOCIATED_ITEM_CODE, $code);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function _setDataValues(array $data)
+    {
+        if (array_key_exists(Item::KEY_TAX_CLASS_KEY, $data)) {
+            $data[Item::KEY_TAX_CLASS_KEY] = $this->taxClassKeyBuilder->populateWithArray(
+                $data[Item::KEY_TAX_CLASS_KEY]
+            )->create();
+        }
+
+        return parent::_setDataValues($data);
+    }
 }
diff --git a/app/code/Magento/Tax/Service/V1/Data/QuoteDetailsBuilder.php b/app/code/Magento/Tax/Service/V1/Data/QuoteDetailsBuilder.php
index 08382bba602c029f2951abf5176f99d808f4d730..dddfa6f4f666e630879abb152ac38c7527c3f6c5 100644
--- a/app/code/Magento/Tax/Service/V1/Data/QuoteDetailsBuilder.php
+++ b/app/code/Magento/Tax/Service/V1/Data/QuoteDetailsBuilder.php
@@ -37,20 +37,37 @@ class QuoteDetailsBuilder extends \Magento\Framework\Service\Data\AbstractObject
      */
     protected $itemBuilder;
 
+    /**
+     * Address builder
+     *
+     * @var \Magento\Customer\Service\V1\Data\AddressBuilder
+     */
+    protected $addressBuilder;
+
+    /**
+     * TaxClassKey builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\TaxClassKeyBuilder
+     */
+    protected $taxClassKeyBuilder;
+
     /**
      * Initialize dependencies.
      *
      * @param \Magento\Framework\Service\Data\ObjectFactory $objectFactory
      * @param \Magento\Tax\Service\V1\Data\QuoteDetails\ItemBuilder $itemBuilder
+     * @param \Magento\Tax\Service\V1\Data\TaxClassKeyBuilder $taxClassKeyBuilder
      * @param \Magento\Customer\Service\V1\Data\AddressBuilder $addressBuilder
      */
     public function __construct(
         \Magento\Framework\Service\Data\ObjectFactory $objectFactory,
         \Magento\Tax\Service\V1\Data\QuoteDetails\ItemBuilder $itemBuilder,
+        \Magento\Tax\Service\V1\Data\TaxClassKeyBuilder $taxClassKeyBuilder,
         \Magento\Customer\Service\V1\Data\AddressBuilder $addressBuilder
     ) {
         parent::__construct($objectFactory);
         $this->itemBuilder = $itemBuilder;
+        $this->taxClassKeyBuilder = $taxClassKeyBuilder;
         $this->addressBuilder = $addressBuilder;
     }
 
@@ -74,6 +91,16 @@ class QuoteDetailsBuilder extends \Magento\Framework\Service\Data\AbstractObject
         return $this->addressBuilder;
     }
 
+    /**
+     * Get tax class key builder
+     *
+     * @return TaxClassKeyBuilder
+     */
+    public function getTaxClassKeyBuilder()
+    {
+        return $this->taxClassKeyBuilder;
+    }
+
     /**
      * Set customer billing address
      *
@@ -97,14 +124,14 @@ class QuoteDetailsBuilder extends \Magento\Framework\Service\Data\AbstractObject
     }
 
     /**
-     * Set customer tax class id
+     * Set customer tax class key
      *
-     * @param int $taxClassId
+     * @param \Magento\Tax\Service\V1\Data\TaxClassKey $taxClassKey
      * @return $this
      */
-    public function setCustomerTaxClassId($taxClassId)
+    public function setCustomerTaxClassKey($taxClassKey)
     {
-        return $this->_set(QuoteDetails::KEY_CUSTOMER_TAX_CLASS_ID, $taxClassId);
+        return $this->_set(QuoteDetails::KEY_CUSTOMER_TAX_CLASS_KEY, $taxClassKey);
     }
 
     /**
@@ -151,6 +178,11 @@ class QuoteDetailsBuilder extends \Magento\Framework\Service\Data\AbstractObject
             }
             $data[QuoteDetails::KEY_ITEMS] = $items;
         }
+        if (array_key_exists(QuoteDetails::KEY_CUSTOMER_TAX_CLASS_KEY, $data)) {
+            $data[QuoteDetails::KEY_CUSTOMER_TAX_CLASS_KEY] = $this->taxClassKeyBuilder->populateWithArray(
+                $data[QuoteDetails::KEY_CUSTOMER_TAX_CLASS_KEY]
+            )->create();
+        }
         return parent::_setDataValues($data);
     }
 }
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxClassKey.php b/app/code/Magento/Tax/Service/V1/Data/TaxClassKey.php
new file mode 100644
index 0000000000000000000000000000000000000000..ef9585faf8313d2f236294992a1ea464feda6ca7
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxClassKey.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1\Data;
+
+use Magento\Framework\Service\Data\AbstractObject;
+
+/**
+ * Class TaxClassKey
+ */
+class TaxClassKey extends AbstractObject
+{
+    /**#@+
+     * Constants defined for keys of array, makes typos less likely
+     */
+    const KEY_TYPE = 'type';
+
+    const KEY_VALUE = 'value';
+    /**#@-*/
+
+    /**#@+
+     * Constants defined for type of tax class key
+     */
+    const TYPE_ID = 'id';
+
+    const TYPE_NAME = 'name';
+    /**#@-*/
+
+    /**
+     * Get type of tax class key
+     *
+     * @return string
+     */
+    public function getType()
+    {
+        return $this->_get(self::KEY_TYPE);
+    }
+
+    /**
+     * Get value of tax class key
+     *
+     * @return string
+     */
+    public function getValue()
+    {
+        return $this->_get(self::KEY_VALUE);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxClassKeyBuilder.php b/app/code/Magento/Tax/Service/V1/Data/TaxClassKeyBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..ed6b6e2b1f0df64ed89ba2a7eb2c4702d50ed179
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxClassKeyBuilder.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1\Data;
+
+use Magento\Framework\Service\Data\AbstractObjectBuilder;
+
+/**
+ * Builder for the TaxClassKey Service Data Object
+ *
+ * @method TaxClassKey create()
+ */
+class TaxClassKeyBuilder extends AbstractObjectBuilder
+{
+    /**
+     * Set type of tax class key
+     *
+     * @param string $type
+     * @return $this
+     */
+    public function setType($type)
+    {
+        return $this->_set(TaxClassKey::KEY_TYPE, $type);
+    }
+
+    /**
+     * Set value of tax class key
+     *
+     * @param String $value
+     * @return $this
+     */
+    public function setValue($value)
+    {
+        return $this->_set(TaxClassKey::KEY_VALUE, $value);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxDetails/Item.php b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/Item.php
index 8146c35a02858ffdad5f56fb181425d2bc4fcdc7..dbec30a30e9d96f31081cfe5d269e1293e98e095 100644
--- a/app/code/Magento/Tax/Service/V1/Data/TaxDetails/Item.php
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/Item.php
@@ -52,6 +52,8 @@ class Item extends \Magento\Framework\Service\Data\AbstractObject
     const KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT = 'discount_tax_compensation_amount';
 
     const KEY_APPLIED_TAXES = 'applied_taxes';
+
+    const KEY_ASSOCIATED_ITEM_CODE = 'associated_item_code';
     /**#@-*/
 
     /**
@@ -173,4 +175,14 @@ class Item extends \Magento\Framework\Service\Data\AbstractObject
     {
         return $this->_get(self::KEY_APPLIED_TAXES);
     }
+
+    /**
+     * Return associated item code if this item is associated with another item, null otherwise
+     *
+     * @return mixed|null
+     */
+    public function getAssociatedItemCode()
+    {
+        return $this->_get(self::KEY_ASSOCIATED_ITEM_CODE);
+    }
 }
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxDetails/ItemBuilder.php b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/ItemBuilder.php
index f10479c1fc686b8fade45467273e8d60eb8c4500..4bca388e1a4054219f21a6073e07b9c17c0159d7 100644
--- a/app/code/Magento/Tax/Service/V1/Data/TaxDetails/ItemBuilder.php
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/ItemBuilder.php
@@ -208,22 +208,32 @@ class ItemBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
         return $this;
     }
 
+    /**
+     * Set the associated item code
+     *
+     * @param string $code
+     * @return $this
+     */
+    public function setAssociatedItemCode($code)
+    {
+        $this->_set(Item::KEY_ASSOCIATED_ITEM_CODE, $code);
+        return $this;
+    }
+
     /**
      * {@inheritdoc}
      */
     protected function _setDataValues(array $data)
     {
-        $appliedTaxDataObjects = [];
-
         if (isset($data[Item::KEY_APPLIED_TAXES])) {
+            $appliedTaxDataObjects = [];
             $appliedTaxes = $data[Item::KEY_APPLIED_TAXES];
             foreach ($appliedTaxes as $appliedTax) {
                 $appliedTaxDataObjects[] = $this->appliedTaxBuilder->populateWithArray($appliedTax)->create();
             }
+            $data[Item::KEY_APPLIED_TAXES] = $appliedTaxDataObjects;
         }
 
-        $data[Item::KEY_APPLIED_TAXES] = $appliedTaxDataObjects;
-
         return parent::_setDataValues($data);
     }
 }
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxRate.php b/app/code/Magento/Tax/Service/V1/Data/TaxRate.php
index 7f16788a0e9ecece10d787da1c9a2a3d6ebe81d4..d3203bc8bace624cf32f571eaa89ce1296d123fa 100644
--- a/app/code/Magento/Tax/Service/V1/Data/TaxRate.php
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxRate.php
@@ -66,7 +66,7 @@ class TaxRate extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Get region id
      *
-     * @return int
+     * @return int|null
      */
     public function getRegionId()
     {
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxRule.php b/app/code/Magento/Tax/Service/V1/Data/TaxRule.php
index 60a9897a05bc777d10475510bbbae4bc8492a874..120b006fe1574a3e551e9f98d9aa8964fb322c3c 100644
--- a/app/code/Magento/Tax/Service/V1/Data/TaxRule.php
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxRule.php
@@ -74,7 +74,7 @@ class TaxRule extends AbstractObject
     /**
      * Get customer tax class id
      *
-     * @return int[]|null
+     * @return int[]
      */
     public function getCustomerTaxClassIds()
     {
@@ -84,7 +84,7 @@ class TaxRule extends AbstractObject
     /**
      * Get product tax class id
      *
-     * @return int[]|null
+     * @return int[]
      */
     public function getProductTaxClassIds()
     {
@@ -94,7 +94,7 @@ class TaxRule extends AbstractObject
     /**
      * Get tax rate ids
      *
-     * @return string[]|null
+     * @return int[]
      */
     public function getTaxRateIds()
     {
@@ -124,7 +124,7 @@ class TaxRule extends AbstractObject
     /**
      * Get calculate subtotal.
      *
-     * @return int|null
+     * @return bool|null
      */
     public function getCalculateSubtotal()
     {
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxRuleBuilder.php b/app/code/Magento/Tax/Service/V1/Data/TaxRuleBuilder.php
index 82bbb0d517a557495fc9e982345ca1f304f2660e..3c420fa1ff7ceee182beb047554895dfa7ca4a22 100644
--- a/app/code/Magento/Tax/Service/V1/Data/TaxRuleBuilder.php
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxRuleBuilder.php
@@ -133,11 +133,11 @@ class TaxRuleBuilder extends AbstractObjectBuilder
     /**
      * Set calculate subtotal.
      *
-     * @param int $calculateSubtotal
+     * @param bool $calculateSubtotal
      * @return $this
      */
     public function setCalculateSubtotal($calculateSubtotal)
     {
-        return $this->_set(TaxRule::CALCULATE_SUBTOTAL, (int)$calculateSubtotal);
+        return $this->_set(TaxRule::CALCULATE_SUBTOTAL, (bool)$calculateSubtotal);
     }
 }
diff --git a/app/code/Magento/Tax/Service/V1/TaxCalculationService.php b/app/code/Magento/Tax/Service/V1/TaxCalculationService.php
index 928779b7911480aa82f37e67609a1cfac6c41365..6ba8e66711a52bdbb97f3bf616f8b8287f4fe6bf 100644
--- a/app/code/Magento/Tax/Service/V1/TaxCalculationService.php
+++ b/app/code/Magento/Tax/Service/V1/TaxCalculationService.php
@@ -30,12 +30,15 @@ use Magento\Tax\Model\Calculation;
 use Magento\Tax\Model\Resource\Sales\Order\Tax;
 use Magento\Tax\Service\V1\Data\QuoteDetails;
 use Magento\Tax\Service\V1\Data\QuoteDetails\Item as QuoteDetailsItem;
+use Magento\Tax\Service\V1\Data\TaxClass;
+use Magento\Tax\Service\V1\Data\TaxClassKey;
 use Magento\Tax\Service\V1\Data\TaxDetails;
 use Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax;
 use Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxRate;
 use Magento\Tax\Service\V1\Data\TaxDetails\Item as TaxDetailsItem;
 use Magento\Tax\Service\V1\Data\TaxDetails\ItemBuilder as TaxDetailsItemBuilder;
 use Magento\Tax\Service\V1\Data\TaxDetailsBuilder;
+use Magento\Tax\Model\Calculation\CalculatorFactory;
 
 /**
  * Tax Calculation Service
@@ -43,22 +46,12 @@ use Magento\Tax\Service\V1\Data\TaxDetailsBuilder;
  */
 class TaxCalculationService implements TaxCalculationServiceInterface
 {
-    /**#@+
-     * Constants for delta rounding key
-     */
-    const KEY_REGULAR_DELTA_ROUNDING = 'regular';
-
-    const KEY_APPLIED_TAX_DELTA_ROUNDING = 'applied_tax_amount';
-
-    const KEY_TAX_AFTER_DISCOUNT_DELTA_ROUNDING = 'tax_after_discount';
-    /**#@-*/
-
     /**
      * Tax calculation model
      *
      * @var Calculation
      */
-    protected $calculator;
+    protected $calculationTool;
 
     /**
      * Tax configuration object
@@ -74,19 +67,6 @@ class TaxCalculationService implements TaxCalculationServiceInterface
      */
     protected $taxDetailsBuilder;
 
-    /**
-     * Rounding deltas for prices
-     *
-     * @var array
-     * example:
-     *  [
-     *      'type' => [
-     *          'rate' => 'rounding delta',
-     *      ],
-     *  ]
-     */
-    protected $roundingDeltas;
-
     /**
      * Array to hold discount compensations for items
      *
@@ -125,30 +105,50 @@ class TaxCalculationService implements TaxCalculationServiceInterface
      */
     protected $customerAccountService;
 
+    /**
+     * Tax Class Service
+     *
+     * @var TaxClassService
+     */
+    protected $taxClassService;
+
+    /**
+     * Calculator Factory
+     *
+     * @var CalculatorFactory
+     */
+    protected $calculatorFactory;
+
     /**
      * Constructor
      *
      * @param Calculation $calculation
+     * @param CalculatorFactory $calculatorFactory
      * @param \Magento\Tax\Model\Config $config
      * @param TaxDetailsBuilder $taxDetailsBuilder
      * @param TaxDetailsItemBuilder $taxDetailsItemBuilder
      * @param StoreManagerInterface $storeManager
      * @param CustomerAccountServiceInterface $customerAccountService
+     * @param TaxClassService $taxClassService
      */
     public function __construct(
         Calculation $calculation,
+        CalculatorFactory $calculatorFactory,
         \Magento\Tax\Model\Config $config,
         TaxDetailsBuilder $taxDetailsBuilder,
         TaxDetailsItemBuilder $taxDetailsItemBuilder,
         StoreManagerInterface $storeManager,
-        CustomerAccountServiceInterface $customerAccountService
+        CustomerAccountServiceInterface $customerAccountService,
+        TaxClassService $taxClassService
     ) {
-        $this->calculator = $calculation;
+        $this->calculationTool = $calculation;
+        $this->calculatorFactory = $calculatorFactory;
         $this->config = $config;
         $this->taxDetailsBuilder = $taxDetailsBuilder;
         $this->taxDetailsItemBuilder = $taxDetailsItemBuilder;
         $this->storeManager = $storeManager;
         $this->customerAccountService = $customerAccountService;
+        $this->taxClassService = $taxClassService;
     }
 
     /**
@@ -175,38 +175,22 @@ class TaxCalculationService implements TaxCalculationServiceInterface
         }
         $this->computeRelationships($items);
 
-        $addressRequest = $this->getAddressTaxRequest($quoteDetails, $storeId, $quoteDetails->getCustomerId());
-        if ($this->config->priceIncludesTax($storeId)) {
-            $storeRequest = $this->getStoreTaxRequest($storeId);
-            $classIds = [];
-            foreach ($items as $item) {
-                if ($item->getTaxClassId()) {
-                    $classIds[] = $item->getTaxClassId();
-                }
-            }
-            $classIds = array_unique($classIds);
-            $addressRequest->setProductClassId($classIds);
-            $storeRequest->setProductClassId($classIds);
-            if ((bool)$this->config->crossBorderTradeEnabled($storeId)) {
-                $addressRequest->setSameRateAsStore(true);
-            } else {
-                $addressRequest->setSameRateAsStore(
-                    $this->calculator->compareRequests($storeRequest, $addressRequest)
-                );
-            }
-        }
+        $calculator = $this->calculatorFactory->create(
+            $this->config->getAlgorithm($storeId),
+            $storeId,
+            $quoteDetails->getBillingAddress(),
+            $quoteDetails->getShippingAddress(),
+            $this->taxClassService->getTaxClassId($quoteDetails->getCustomerTaxClassKey(), 'customer'),
+            $quoteDetails->getCustomerId()
+        );
 
-        // init rounding deltas for this quote
-        $this->roundingDeltas = [];
-        // init discount tax compensations array
-        $this->discountTaxCompensations = [];
         $processedItems = [];
         /** @var QuoteDetailsItem $item */
         foreach ($this->keyedItems as $item) {
             if (isset($this->parentToChildren[$item->getCode()])) {
                 $processedChildren = [];
                 foreach ($this->parentToChildren[$item->getCode()] as $child) {
-                    $processedItem = $this->processItem($child, $addressRequest, $storeId);
+                    $processedItem = $this->processItem($child, $calculator);
                     $taxDetailsData = $this->aggregateItemData($taxDetailsData, $processedItem);
                     $processedItems[$processedItem->getCode()] = $processedItem;
                     $processedChildren[] = $processedItem;
@@ -216,7 +200,7 @@ class TaxCalculationService implements TaxCalculationServiceInterface
                 $processedItemBuilder->setType($item->getType());
                 $processedItem = $processedItemBuilder->create();
             } else {
-                $processedItem = $this->processItem($item, $addressRequest, $storeId);
+                $processedItem = $this->processItem($item, $calculator);
                 $taxDetailsData = $this->aggregateItemData($taxDetailsData, $processedItem);
             }
             $processedItems[$processedItem->getCode()] = $processedItem;
@@ -266,12 +250,12 @@ class TaxCalculationService implements TaxCalculationServiceInterface
             $storeId = $this->storeManager->getStore()->getStoreId();
         }
         if (!$isDefault) {
-            $addressRequestObject = $this->calculator->getRateRequest(null, null, null, $storeId, $customerId);
+            $addressRequestObject = $this->calculationTool->getRateRequest(null, null, null, $storeId, $customerId);
         } else {
-            $addressRequestObject = $this->calculator->getDefaultRateRequest($storeId, $customerId);
+            $addressRequestObject = $this->calculationTool->getDefaultRateRequest($storeId, $customerId);
         }
         $addressRequestObject->setProductClassId($productTaxClassID);
-        return $this->calculator->getRate($addressRequestObject);
+        return $this->calculationTool->getRate($addressRequestObject);
     }
 
     /**
@@ -293,453 +277,19 @@ class TaxCalculationService implements TaxCalculationServiceInterface
         }
     }
 
-    /**
-     * Get request for fetching address tax rate
-     *
-     * @param QuoteDetails $quoteDetails
-     * @param int $storeId
-     * @param int $customerId
-     * @return \Magento\Framework\Object
-     */
-    protected function getAddressTaxRequest(QuoteDetails $quoteDetails, $storeId, $customerId)
-    {
-        return $this->calculator->getRateRequest(
-            $quoteDetails->getShippingAddress(),
-            $quoteDetails->getBillingAddress(),
-            $quoteDetails->getCustomerTaxClassId(),
-            $storeId,
-            $customerId
-        );
-    }
-
-    /**
-     * Get request for fetching store tax rate
-     *
-     * @param int $storeId
-     * @return \Magento\Framework\Object
-     */
-    protected function getStoreTaxRequest($storeId)
-    {
-        return $this->calculator->getRateOriginRequest($storeId);
-    }
-
     /**
      * Calculate item tax with customized rounding level
      *
      * @param QuoteDetailsItem $item
-     * @param \Magento\Framework\Object $taxRequest
-     * @param int $storeId
-     * @return TaxDetailsItem|null
-     */
-    protected function processItem(
-        QuoteDetailsItem $item,
-        \Magento\Framework\Object $taxRequest,
-        $storeId
-    ) {
-        switch ($this->config->getAlgorithm($storeId)) {
-            case Calculation::CALC_UNIT_BASE:
-                return $this->unitBaseCalculation($item, $taxRequest, $storeId);
-            case Calculation::CALC_ROW_BASE:
-            case Calculation::CALC_TOTAL_BASE:
-                return $this->totalBaseCalculation($item, $taxRequest, $storeId);
-            default:
-                return null;
-        }
-    }
-
-    /**
-     * Calculate item price and row total including/excluding tax based on unit price rounding level
-     * This function also saves applied tax per tax rate for the item
-     *
-     * @param QuoteDetailsItem $item
-     * @param \Magento\Framework\Object $taxRateRequest
-     * @param int $storeId
+     * @param Calculation\AbstractCalculator $calculator
      * @return TaxDetailsItem
      */
-    protected function unitBaseCalculation(
-        QuoteDetailsItem $item,
-        \Magento\Framework\Object $taxRateRequest,
-        $storeId
-    ) {
-        /** @var  \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[] $appliedTaxes */
-        $appliedTaxes = [];
-        $appliedTaxBuilder = $this->taxDetailsItemBuilder->getAppliedTaxBuilder();
-        $appliedTaxRateBuilder = $appliedTaxBuilder->getAppliedTaxRateBuilder();
-
-        $taxRateRequest->setProductClassId($item->getTaxClassId());
-        $appliedRates = $this->calculator->getAppliedRates($taxRateRequest);
-        $rate = $this->calculator->getRate($taxRateRequest);
-
-        $quantity = $this->getTotalQuantity($item);
-        $price = $priceInclTax = $this->calculator->round($item->getUnitPrice());
-        $rowTotal = $rowTotalInclTax = $this->calcRowTotal($item);
-
-        $discountAmount = $item->getDiscountAmount();
-        $applyTaxAfterDiscount = $this->config->applyTaxAfterDiscount($storeId);
-
-        $discountTaxCompensationAmount = 0;
-
-        if ($item->getTaxIncluded()) {
-            if ($taxRateRequest->getSameRateAsStore()) {
-                $uniTax = $this->calculator->calcTaxAmount($priceInclTax, $rate, true);
-                $price = $priceInclTax - $uniTax;
-                $rowTax = $uniTax * $quantity;
-                $rowTotal = $price * $quantity;
-            } else {
-                $storeRate = $this->calculator->getStoreRate($taxRateRequest, $storeId);
-                $priceInclTax = $this->calculatePriceInclTax($price, $storeRate, $rate);
-                $uniTax = $this->calculator->calcTaxAmount($priceInclTax, $rate, true, true);
-                $rowTax = $uniTax * $quantity;
-                $price = $priceInclTax - $uniTax;
-                $rowTotalInclTax = $priceInclTax * $quantity;
-                $rowTotal = $price * $quantity;
-            }
-
-            //Handle discount
-            if ($discountAmount && $applyTaxAfterDiscount) {
-                //TODO: handle originalDiscountAmount
-                $unitDiscountAmount = $discountAmount / $quantity;
-                $taxableAmount = max($priceInclTax - $unitDiscountAmount, 0);
-                $unitTaxAfterDiscount = $this->calculator->calcTaxAmount(
-                    $taxableAmount,
-                    $rate,
-                    true,
-                    true
-                );
-
-                // Set discount tax compensation
-                $unitDiscountTaxCompensationAmount = $uniTax - $unitTaxAfterDiscount;
-                $discountTaxCompensationAmount = $unitDiscountTaxCompensationAmount * $quantity;
-                $rowTax = $unitTaxAfterDiscount * $quantity;
-            }
-
-            //save applied taxes
-            $appliedTaxes = $this->getAppliedTaxes($appliedTaxBuilder, $rowTax, $rate, $appliedRates);
-        } else { //catalog price does not include tax
-            $taxable = $price;
-            $appliedRates = $this->calculator->getAppliedRates($taxRateRequest);
-            $unitTaxes = [];
-            $unitTaxesBeforeDiscount = [];
-            //Apply each tax rate separately
-            foreach ($appliedRates as $appliedRate) {
-                $taxId = $appliedRate['id'];
-                $taxRate = $appliedRate['percent'];
-                $unitTaxPerRate = $this->calculator->calcTaxAmount($taxable, $taxRate, false);
-                $unitTaxAfterDiscount = $unitTaxPerRate;
-
-                //Handle discount
-                if ($discountAmount && $applyTaxAfterDiscount) {
-                    //TODO: handle originalDiscountAmount
-                    $unitDiscountAmount = $discountAmount / $quantity;
-                    $taxableAmount = max($priceInclTax - $unitDiscountAmount, 0);
-                    $unitTaxAfterDiscount = $this->calculator->calcTaxAmount(
-                        $taxableAmount,
-                        $taxRate,
-                        false,
-                        true
-                    );
-                }
-                $appliedTaxes[$taxId] = $this->getAppliedTax(
-                    $appliedTaxBuilder,
-                    $unitTaxAfterDiscount * $quantity,
-                    $appliedRate
-                );
-
-                $unitTaxes[] = $unitTaxAfterDiscount;
-                $unitTaxesBeforeDiscount[] = $unitTaxPerRate;
-            }
-            $unitTax = array_sum($unitTaxes);
-            $unitTaxBeforeDiscount = array_sum($unitTaxesBeforeDiscount);
-            $rowTax = $unitTax * $quantity;
-            $priceInclTax = $price + $unitTaxBeforeDiscount;
-            $rowTotalInclTax = $priceInclTax * $quantity;
-        }
-
-        $this->taxDetailsItemBuilder->setCode($item->getCode());
-        $this->taxDetailsItemBuilder->setRowTax($rowTax);
-        $this->taxDetailsItemBuilder->setPrice($price);
-        $this->taxDetailsItemBuilder->setPriceInclTax($priceInclTax);
-        $this->taxDetailsItemBuilder->setRowTotal($rowTotal);
-        $this->taxDetailsItemBuilder->setRowTotalInclTax($rowTotalInclTax);
-        $this->taxDetailsItemBuilder->setCode($item->getCode());
-        $this->taxDetailsItemBuilder->setType($item->getType());
-        $this->taxDetailsItemBuilder->setTaxPercent($rate);
-        $this->taxDetailsItemBuilder->setDiscountTaxCompensationAmount($discountTaxCompensationAmount);
-
-        $this->taxDetailsItemBuilder->setAppliedTaxes($appliedTaxes);
-        return $this->taxDetailsItemBuilder->create();
-    }
-
-    /**
-     * Create AppliedTax data object based applied tax rates and tax amount
-     *
-     * @param \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder $appliedTaxBuilder
-     * @param float $rowTax
-     * @param array $appliedRate
-     * @return \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax
-     */
-    protected function getAppliedTax($appliedTaxBuilder, $rowTax, $appliedRate)
-    {
-        $appliedTaxRateBuilder = $appliedTaxBuilder->getAppliedTaxRateBuilder();
-        $appliedTaxBuilder->setAmount($rowTax);
-        $appliedTaxBuilder->setPercent($appliedRate['percent']);
-        $appliedTaxBuilder->setTaxRateKey($appliedRate['id']);
-
-        /** @var  AppliedTaxRate[] $rateDataObjects */
-        $rateDataObjects = [];
-        foreach ($appliedRate['rates'] as $rate) {
-            $appliedTaxRateBuilder->setPercent($rate['percent']);
-            $appliedTaxRateBuilder->setCode($rate['code']);
-            $appliedTaxRateBuilder->setTitle($rate['title']);
-            //Skipped position, priority and rule_id
-            $rateDataObjects[$rate['code']] = $appliedTaxRateBuilder->create();
-        }
-        $appliedTaxBuilder->setRates($rateDataObjects);
-        $appliedTax = $appliedTaxBuilder->create();
-        return $appliedTax;
-    }
-
-    /**
-     * Create AppliedTax data object based on applied tax rates and tax amount
-     *
-     * @param \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder $appliedTaxBuilder
-     * @param float $rowTax
-     * @param float $totalTaxRate
-     * @param array $appliedRates May contain multiple tax rates when catalog price includes tax
-     * @return \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[]
-     */
-    protected function getAppliedTaxes($appliedTaxBuilder, $rowTax, $totalTaxRate, $appliedRates)
-    {
-        /** @var \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[] $appliedTaxes */
-        $appliedTaxes = [];
-        $appliedTaxRateBuilder = $appliedTaxBuilder->getAppliedTaxRateBuilder();
-        $totalAppliedAmount = 0;
-        foreach ($appliedRates as $appliedRate) {
-            if ($appliedRate['percent'] == 0) {
-                continue;
-            }
-
-            $appliedAmount = $rowTax / $totalTaxRate * $appliedRate['percent'];
-            //Use delta rounding to split tax amounts for each tax rates between items
-            $appliedAmount = $this->deltaRound(
-                $appliedAmount,
-                $appliedRate['id'],
-                true,
-                self::KEY_APPLIED_TAX_DELTA_ROUNDING
-            );
-            if ($totalAppliedAmount + $appliedAmount > $rowTax) {
-                $appliedAmount = $rowTax - $totalAppliedAmount;
-            }
-            $totalAppliedAmount += $appliedAmount;
-
-            $appliedTaxBuilder->setAmount($appliedAmount);
-            $appliedTaxBuilder->setPercent($appliedRate['percent']);
-            $appliedTaxBuilder->setTaxRateKey($appliedRate['id']);
-
-            /** @var  AppliedTaxRate[] $rateDataObjects */
-            $rateDataObjects = [];
-            foreach ($appliedRate['rates'] as $rate) {
-                $appliedTaxRateBuilder->setPercent($rate['percent']);
-                $appliedTaxRateBuilder->setCode($rate['code']);
-                $appliedTaxRateBuilder->setTitle($rate['title']);
-                //Skipped position, priority and rule_id
-                $rateDataObjects[$rate['code']] = $appliedTaxRateBuilder->create();
-            }
-            $appliedTaxBuilder->setRates($rateDataObjects);
-            $appliedTax = $appliedTaxBuilder->create();
-            $appliedTaxes[$appliedTax->getTaxRateKey()] = $appliedTax;
-        }
-
-        return $appliedTaxes;
-    }
-
-    /**
-     * Calculate item price and row total including/excluding tax based on total price rounding level
-     *
-     * @param QuoteDetailsItem $item
-     * @param \Magento\Framework\Object $taxRateRequest
-     * @param int $storeId
-     * @return TaxDetailsItem
-     */
-    protected function totalBaseCalculation(
+    protected function processItem(
         QuoteDetailsItem $item,
-        \Magento\Framework\Object $taxRateRequest,
-        $storeId
+        Calculation\AbstractCalculator $calculator
     ) {
-        /** @var  \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[] $appliedTaxes */
-        $appliedTaxes = [];
-        $appliedTaxBuilder = $this->taxDetailsItemBuilder->getAppliedTaxBuilder();
-        $appliedTaxRateBuilder = $appliedTaxBuilder->getAppliedTaxRateBuilder();
-
-        $taxRateRequest->setProductClassId($item->getTaxClassId());
-        $appliedRates = $this->calculator->getAppliedRates($taxRateRequest);
-        $rate = $this->calculator->getRate($taxRateRequest);
-
         $quantity = $this->getTotalQuantity($item);
-        $price = $priceInclTax = $this->calculator->round($item->getUnitPrice());
-        $rowTotal = $rowTotalInclTax = $taxableAmount = $this->calcRowTotal($item);
-
-        $discountAmount = $item->getDiscountAmount();
-        $applyTaxAfterDiscount = $this->config->applyTaxAfterDiscount($storeId);
-
-        $discountTaxCompensationAmount = 0;
-
-        $isTotalBasedCalculation = ($this->config->getAlgorithm($storeId) == Calculation::CALC_TOTAL_BASE);
-
-        if ($item->getTaxIncluded()) {
-            if ($taxRateRequest->getSameRateAsStore()) {
-                $rowTaxExact = $this->calculator->calcTaxAmount($rowTotalInclTax, $rate, true, false);
-                if ($isTotalBasedCalculation) {
-                    $rowTax = $this->deltaRound($rowTaxExact, $rate, true);
-                } else {
-                    $rowTax = $this->calculator->round($rowTaxExact);
-                }
-                $rowTotal = $rowTotalInclTax - $rowTax;
-                $price = $this->calculator->round($rowTotal / $quantity);
-            } else {
-                $storeRate = $this->calculator->getStoreRate($taxRateRequest, $storeId);
-                $priceInclTax = $this->calculatePriceInclTax($price, $storeRate, $rate);
-                $rowTotalInclTax = $priceInclTax * $quantity;
-                $taxableAmount = $rowTotalInclTax;
-                if ($isTotalBasedCalculation) {
-                    $rowTax = $this->deltaRound(
-                        $this->calculator->calcTaxAmount($rowTotalInclTax, $rate, true, false),
-                        $rate,
-                        true
-                    );
-                } else {
-                    $rowTax = $this->calculator->calcTaxAmount($rowTotalInclTax, $rate, true, true);
-                }
-                $rowTotal = $rowTotalInclTax - $rowTax;
-                $price = $this->calculator->round($rowTotal / $quantity);
-            }
-
-            //Handle discount
-            if ($discountAmount && $applyTaxAfterDiscount) {
-                //TODO: handle originalDiscountAmount
-                $taxableAmount = max($taxableAmount - $discountAmount, 0);
-                $rowTaxAfterDiscount = $this->calculator->calcTaxAmount(
-                    $taxableAmount,
-                    $rate,
-                    true,
-                    false
-                );
-                if ($isTotalBasedCalculation) {
-                    //Round the row tax using a different type so that we don't pollute the rounding deltas
-                    $rowTaxAfterDiscount = $this->deltaRound(
-                        $rowTaxAfterDiscount,
-                        $rate,
-                        true,
-                        self::KEY_TAX_AFTER_DISCOUNT_DELTA_ROUNDING
-                    );
-                } else {
-                    $rowTaxAfterDiscount = $this->calculator->round($rowTaxAfterDiscount);
-                }
-
-                // Set discount tax compensation
-                $discountTaxCompensationAmount = $rowTax - $rowTaxAfterDiscount;
-                $rowTax = $rowTaxAfterDiscount;
-            }
-
-            //save applied taxes
-            $appliedTaxes = $this->getAppliedTaxes(
-                $appliedTaxBuilder,
-                $rowTax,
-                $rate,
-                $appliedRates
-            );
-        } else { //catalog price does not include tax
-            $appliedRates = $this->calculator->getAppliedRates($taxRateRequest);
-            $rowTaxes = [];
-            $rowTaxesBeforeDiscount = [];
-            //Apply each tax rate separately
-            foreach ($appliedRates as $appliedRate) {
-                $taxId = $appliedRate['id'];
-                $taxRate = $appliedRate['percent'];
-                if ($isTotalBasedCalculation) {
-                    $rowTaxPerRate = $this->deltaRound(
-                        $this->calculator->calcTaxAmount($rowTotal, $taxRate, false, false),
-                        $taxId,
-                        false
-                    );
-                } else {
-                    $rowTaxPerRate = $this->calculator->calcTaxAmount($rowTotal, $taxRate, false, true);
-                }
-                $rowTaxAfterDiscount = $rowTaxPerRate;
-                //Handle discount
-                if ($discountAmount && $applyTaxAfterDiscount) {
-                    //TODO: handle originalDiscountAmount
-                    $rowTaxAfterDiscount = $this->calculator->calcTaxAmount(
-                        max($rowTotal - $discountAmount, 0),
-                        $taxRate,
-                        false,
-                        false
-                    );
-                    if ($isTotalBasedCalculation) {
-                        //Round the row tax using a different type so that we don't pollute the rounding deltas
-                        $rowTaxAfterDiscount = $this->deltaRound(
-                            $rowTaxAfterDiscount,
-                            $taxRate,
-                            false,
-                            self::KEY_TAX_AFTER_DISCOUNT_DELTA_ROUNDING
-                        );
-                    } else {
-                        $rowTaxAfterDiscount = $this->calculator->round($rowTaxAfterDiscount);
-                    }
-                }
-                $appliedTaxes[$appliedRate['id']] = $this->getAppliedTax(
-                    $appliedTaxBuilder,
-                    $rowTaxAfterDiscount,
-                    $appliedRate
-                );
-                $rowTaxes[] = $rowTaxAfterDiscount;
-                $rowTaxesBeforeDiscount[] = $rowTaxPerRate;
-            }
-            $rowTax = array_sum($rowTaxes);
-            $rowTaxBeforeDiscount = array_sum($rowTaxesBeforeDiscount);
-            $rowTotalInclTax = $rowTotal + $rowTaxBeforeDiscount;
-            $priceInclTax = $this->calculator->round($rowTotalInclTax / $quantity);
-        }
-
-        $this->taxDetailsItemBuilder->setCode($item->getCode());
-        $this->taxDetailsItemBuilder->setRowTax($rowTax);
-        $this->taxDetailsItemBuilder->setPrice($price);
-        $this->taxDetailsItemBuilder->setPriceInclTax($priceInclTax);
-        $this->taxDetailsItemBuilder->setRowTotal($rowTotal);
-        $this->taxDetailsItemBuilder->setRowTotalInclTax($rowTotalInclTax);
-        $this->taxDetailsItemBuilder->setCode($item->getCode());
-        $this->taxDetailsItemBuilder->setType($item->getType());
-        $this->taxDetailsItemBuilder->setTaxPercent($rate);
-        $this->taxDetailsItemBuilder->setDiscountTaxCompensationAmount($discountTaxCompensationAmount);
-
-        $this->taxDetailsItemBuilder->setAppliedTaxes($appliedTaxes);
-        return $this->taxDetailsItemBuilder->create();
-    }
-
-    /**
-     * Round price based on previous rounding operation delta
-     *
-     * @param float $price
-     * @param string $rate
-     * @param bool $direction
-     * @param string $type
-     * @return float
-     */
-    protected function deltaRound($price, $rate, $direction, $type = self::KEY_REGULAR_DELTA_ROUNDING)
-    {
-        if ($price) {
-            $rate = (string)$rate;
-            $type = $type . $direction;
-            // initialize the delta to a small number to avoid non-deterministic behavior with rounding of 0.5
-            $delta = isset($this->roundingDeltas[$type][$rate])
-                ? $this->roundingDeltas[$type][$rate]
-                : 0.000001;
-            $price += $delta;
-            $roundPrice = $this->calculator->round($price);
-            $this->roundingDeltas[$type][$rate] = $price - $roundPrice;
-            $price = $roundPrice;
-        }
-        return $price;
+        return $calculator->calculate($item, $quantity);
     }
 
     /**
@@ -763,8 +313,8 @@ class TaxCalculationService implements TaxCalculationServiceInterface
             $taxableAmount += $child->getTaxableAmount();
         }
 
-        $price = $this->calculator->round($rowTotal / $quantity);
-        $priceInclTax = $this->calculator->round($rowTotalInclTax / $quantity);
+        $price = $this->calculationTool->round($rowTotal / $quantity);
+        $priceInclTax = $this->calculationTool->round($rowTotalInclTax / $quantity);
 
         $this->taxDetailsItemBuilder->setPrice($price);
         $this->taxDetailsItemBuilder->setPriceInclTax($priceInclTax);
@@ -775,24 +325,6 @@ class TaxCalculationService implements TaxCalculationServiceInterface
         return $this->taxDetailsItemBuilder;
     }
 
-    /**
-     * Given a store price that includes tax at the store rate, this function will back out the store's tax, and add in
-     * the customer's tax.  Returns this new price which is the customer's price including tax.
-     *
-     * @param float $storePriceInclTax
-     * @param float $storeRate
-     * @param float $customerRate
-     * @return float
-     */
-    protected function calculatePriceInclTax($storePriceInclTax, $storeRate, $customerRate)
-    {
-        $storeTax = $this->calculator->calcTaxAmount($storePriceInclTax, $storeRate, true, false);
-        $priceExclTax = $storePriceInclTax - $storeTax;
-        $customerTax = $this->calculator->calcTaxAmount($priceExclTax, $customerRate, false, false);
-        $customerPriceInclTax = $this->calculator->round($priceExclTax + $customerTax);
-        return $customerPriceInclTax;
-    }
-
     /**
      * Add row total item amount to subtotal
      *
@@ -813,8 +345,8 @@ class TaxCalculationService implements TaxCalculationServiceInterface
             + $item->getDiscountTaxCompensationAmount();
 
         $itemAppliedTaxes = $item->getAppliedTaxes();
-        if (!isset($taxDetailsData[TaxDetails::KEY_APPLIED_TAXES])) {
-            $taxDetailsData[TaxDetails::KEY_APPLIED_TAXES] = [];
+        if (is_null($itemAppliedTaxes)) {
+            return $taxDetailsData;
         }
         $appliedTaxes = $taxDetailsData[TaxDetails::KEY_APPLIED_TAXES];
         foreach ($itemAppliedTaxes as $taxId => $itemAppliedTax) {
@@ -861,20 +393,4 @@ class TaxCalculationService implements TaxCalculationServiceInterface
         }
         return $item->getQuantity();
     }
-
-    /**
-     * Calculate the row total for an item
-     *
-     * @param QuoteDetailsItem $item
-     * @return float
-     */
-    protected function calcRowTotal(QuoteDetailsItem $item)
-    {
-        $qty = $this->getTotalQuantity($item);
-
-        // Round unit price before multiplying to prevent losing 1 cent on subtotal
-        $total = $this->calculator->round($item->getUnitPrice()) * $qty;
-
-        return $this->calculator->round($total);
-    }
 }
diff --git a/app/code/Magento/Tax/Service/V1/TaxCalculationServiceInterface.php b/app/code/Magento/Tax/Service/V1/TaxCalculationServiceInterface.php
index 1f663e8d179bb96ade6da1188f70e5faaa6fc2a8..b189b8f0e4d549f8062662696350f9d1d66835f9 100644
--- a/app/code/Magento/Tax/Service/V1/TaxCalculationServiceInterface.php
+++ b/app/code/Magento/Tax/Service/V1/TaxCalculationServiceInterface.php
@@ -26,6 +26,14 @@ namespace Magento\Tax\Service\V1;
 
 interface TaxCalculationServiceInterface
 {
+    /**#@+
+     * Type of calculation used
+     */
+    const CALC_UNIT_BASE = 'UNIT_BASE_CALCULATION';
+    const CALC_ROW_BASE = 'ROW_BASE_CALCULATION';
+    const CALC_TOTAL_BASE = 'TOTAL_BASE_CALCULATION';
+    /**#@-*/
+
     /**
      * Calculate Tax
      *
diff --git a/app/code/Magento/Tax/Service/V1/TaxClassService.php b/app/code/Magento/Tax/Service/V1/TaxClassService.php
index fbcd6c71c2865df5005348f758a1e4bd7648fa95..4303b9f219410feb1751b4a4d12740aaef535b5d 100644
--- a/app/code/Magento/Tax/Service/V1/TaxClassService.php
+++ b/app/code/Magento/Tax/Service/V1/TaxClassService.php
@@ -27,13 +27,17 @@ namespace Magento\Tax\Service\V1;
 use Magento\Framework\Exception\InputException;
 use Magento\Framework\Model\Exception as ModelException;
 use Magento\Framework\Service\V1\Data\Search\FilterGroup;
+use Magento\Framework\Service\V1\Data\FilterBuilder;
 use Magento\Framework\Service\V1\Data\SearchCriteria;
+use Magento\Framework\Service\V1\Data\SearchCriteriaBuilder;
 use Magento\Tax\Model\ClassModelRegistry;
 use Magento\Tax\Model\Converter;
 use Magento\Tax\Model\Resource\TaxClass\Collection as TaxClassCollection;
 use Magento\Tax\Model\Resource\TaxClass\CollectionFactory as TaxClassCollectionFactory;
+use Magento\Tax\Service\V1\Data\TaxClass;
 use Magento\Tax\Service\V1\Data\TaxClassSearchResultsBuilder;
 use Magento\Tax\Service\V1\Data\TaxClass as TaxClassDataObject;
+use Magento\Tax\Service\V1\Data\TaxClassKey;
 use Magento\Framework\Exception\CouldNotDeleteException;
 
 /**
@@ -63,20 +67,40 @@ class TaxClassService implements TaxClassServiceInterface
 
     const CLASS_ID_NOT_ALLOWED = 'class_id is not expected for this request.';
 
+    /**
+     * Search Criteria Builder
+     *
+     * @var SearchCriteriaBuilder
+     */
+    protected $searchCriteriaBuilder;
+
+    /**
+     * Filter Builder
+     *
+     * @var FilterBuilder
+     */
+    protected $filterBuilder;
+
     /**
      * Initialize dependencies.
      *
+     * @param SearchCriteriaBuilder $searchCriteriaBuilder
+     * @param FilterBuilder $filterBuilder
      * @param TaxClassCollectionFactory $taxClassCollectionFactory
      * @param TaxClassSearchResultsBuilder $searchResultsBuilder
      * @param Converter $converter
      * @param ClassModelRegistry $classModelRegistry
      */
     public function __construct(
+        SearchCriteriaBuilder $searchCriteriaBuilder,
+        FilterBuilder $filterBuilder,
         TaxClassCollectionFactory $taxClassCollectionFactory,
         TaxClassSearchResultsBuilder $searchResultsBuilder,
         Converter $converter,
         ClassModelRegistry $classModelRegistry
     ) {
+        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
+        $this->filterBuilder = $filterBuilder;
         $this->taxClassCollectionFactory = $taxClassCollectionFactory;
         $this->searchResultsBuilder = $searchResultsBuilder;
         $this->converter = $converter;
@@ -261,4 +285,32 @@ class TaxClassService implements TaxClassServiceInterface
             $collection->addFieldToFilter($fields, $conditions);
         }
     }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getTaxClassId($taxClassKey, $taxClassType = TaxClassServiceInterface::TYPE_PRODUCT)
+    {
+        if (!empty($taxClassKey)) {
+            switch ($taxClassKey->getType()) {
+                case TaxClassKey::TYPE_ID:
+                    return $taxClassKey->getValue();
+                case TaxClassKey::TYPE_NAME:
+                    $searchCriteria = $this->searchCriteriaBuilder->addFilter(
+                        [$this->filterBuilder->setField(TaxClass::KEY_TYPE)->setValue($taxClassType)->create()]
+                    )->addFilter(
+                        [
+                            $this->filterBuilder->setField(TaxClass::KEY_NAME)
+                                ->setValue($taxClassKey->getValue())
+                                ->create()
+                        ]
+                    )->create();
+                    $taxClasses = $this->searchTaxClass($searchCriteria)->getItems();
+                    $taxClass = array_shift($taxClasses);
+                    return (null == $taxClass) ? null : $taxClass->getClassId();
+                default:
+            }
+        }
+        return null;
+    }
 }
diff --git a/app/code/Magento/Tax/Service/V1/TaxClassServiceInterface.php b/app/code/Magento/Tax/Service/V1/TaxClassServiceInterface.php
index 4a1b4e48f5e5015ff33dbc90d5cbf601d6c9a17b..3e0fecaec15042a66eb3fdcdea72eb0a35ee1ba4 100644
--- a/app/code/Magento/Tax/Service/V1/TaxClassServiceInterface.php
+++ b/app/code/Magento/Tax/Service/V1/TaxClassServiceInterface.php
@@ -84,4 +84,13 @@ interface TaxClassServiceInterface
      * @throws \Magento\Framework\Exception\InputException
      */
     public function searchTaxClass(\Magento\Framework\Service\V1\Data\SearchCriteria $searchCriteria);
+
+    /**
+     * Get tax class id
+     *
+     * @param \Magento\Tax\Service\V1\Data\TaxClassKey|null $taxClassKey
+     * @param string $taxClassType
+     * @return int|null
+     */
+    public function getTaxClassId($taxClassKey, $taxClassType = self::TYPE_PRODUCT);
 }
diff --git a/app/code/Magento/Tax/Service/V1/TaxRateService.php b/app/code/Magento/Tax/Service/V1/TaxRateService.php
index 8c35f798926f1a645df2326f75da370941574d50..2c215d528cf3acf5e48326e2ed08af0ff2a4907d 100644
--- a/app/code/Magento/Tax/Service/V1/TaxRateService.php
+++ b/app/code/Magento/Tax/Service/V1/TaxRateService.php
@@ -26,14 +26,14 @@ namespace Magento\Tax\Service\V1;
 
 use Magento\Framework\Exception\InputException;
 use Magento\Framework\Model\Exception as ModelException;
+use Magento\Framework\Service\V1\Data\Search\FilterGroup;
+use Magento\Framework\Service\V1\Data\SearchCriteria;
+use Magento\Tax\Model\Calculation\Rate as RateModel;
 use Magento\Tax\Model\Calculation\Rate\Converter;
 use Magento\Tax\Model\Calculation\RateFactory;
-use Magento\Tax\Service\V1\Data\TaxRate as TaxRateDataObject;
-use Magento\Tax\Model\Calculation\Rate as RateModel;
 use Magento\Tax\Model\Calculation\RateRegistry;
-use Magento\Framework\Service\V1\Data\SearchCriteria;
 use Magento\Tax\Model\Resource\Calculation\Rate\Collection;
-use Magento\Framework\Service\V1\Data\Search\FilterGroup;
+use Magento\Tax\Service\V1\Data\TaxRate as TaxRateDataObject;
 use Magento\Tax\Service\V1\Data\TaxRateBuilder;
 
 /**
@@ -155,7 +155,10 @@ class TaxRateService implements TaxRateServiceInterface
         $sortOrders = $searchCriteria->getSortOrders();
         if ($sortOrders) {
             foreach ($sortOrders as $field => $direction) {
-                $collection->addOrder($field, $direction == SearchCriteria::SORT_ASC ? 'ASC' : 'DESC');
+                $collection->addOrder(
+                    $this->translateField($field),
+                    $direction == SearchCriteria::SORT_ASC ? 'ASC' : 'DESC'
+                );
             }
         }
         $collection->setCurPage($searchCriteria->getCurrentPage());
@@ -285,8 +288,12 @@ class TaxRateService implements TaxRateServiceInterface
             if ($zipRangeFromTo['zip_from'] > $zipRangeFromTo['zip_to']) {
                 $exception->addError('Range To should be equal or greater than Range From.');
             }
-
+        } else {
+            if (!\Zend_Validate::is(trim($taxRate->getPostcode()), 'NotEmpty')) {
+                $exception->addError(InputException::REQUIRED_FIELD, ['fieldName' => 'postcode']);
+            }
         }
+
         if ($exception->wasErrorAdded()) {
             throw $exception;
         }
diff --git a/app/code/Magento/Tax/Service/V1/TaxRuleService.php b/app/code/Magento/Tax/Service/V1/TaxRuleService.php
index 22f85d053c3df79b863d2b2c19eb958c28dd1323..02f2855cb7bc73cd4b2be7ad7bd6128c81c05dd3 100644
--- a/app/code/Magento/Tax/Service/V1/TaxRuleService.php
+++ b/app/code/Magento/Tax/Service/V1/TaxRuleService.php
@@ -25,16 +25,18 @@
 namespace Magento\Tax\Service\V1;
 
 use Magento\Framework\Exception\InputException;
-use Magento\Framework\Service\V1\Data\SearchCriteria;
+use Magento\Framework\Model\Exception as ModelException;
+use Magento\Framework\Service\V1\Data\FilterBuilder;
 use Magento\Framework\Service\V1\Data\Search\FilterGroup;
+use Magento\Framework\Service\V1\Data\SearchCriteria;
+use Magento\Framework\Service\V1\Data\SearchCriteriaBuilder;
+use Magento\Tax\Model\Calculation\Rule as TaxRuleModel;
+use Magento\Tax\Model\Calculation\RuleFactory as TaxRuleModelFactory;
 use Magento\Tax\Model\Calculation\TaxRuleConverter;
 use Magento\Tax\Model\Calculation\TaxRuleRegistry;
+use Magento\Tax\Model\Resource\Calculation\Rule\Collection;
 use Magento\Tax\Service\V1\Data\TaxRule;
 use Magento\Tax\Service\V1\Data\TaxRuleBuilder;
-use Magento\Tax\Model\Calculation\Rule as TaxRuleModel;
-use Magento\Tax\Model\Calculation\RuleFactory as TaxRuleModelFactory;
-use Magento\Tax\Model\Resource\Calculation\Rule\Collection;
-use Magento\Framework\Model\Exception as ModelException;
 
 /**
  * TaxRuleService implementation.
@@ -68,25 +70,49 @@ class TaxRuleService implements TaxRuleServiceInterface
      */
     protected $taxRuleModelFactory;
 
+    /**
+     * @var FilterBuilder
+     */
+    protected $filterBuilder;
+
+    /**
+     * @var TaxRateServiceInterface
+     */
+    protected $taxRateService;
+
+    /**
+     * @var SearchCriteriaBuilder
+     */
+    protected $searchCriteriaBuilder;
+
     /**
      * @param TaxRuleBuilder $taxRuleBuilder
      * @param TaxRuleConverter $converter
      * @param TaxRuleRegistry $taxRuleRegistry
      * @param Data\TaxRuleSearchResultsBuilder $taxRuleSearchResultsBuilder
      * @param TaxRuleModelFactory $taxRuleModelFactory
+     * @param FilterBuilder $filterBuilder
+     * @param TaxRateServiceInterface $taxRateService
+     * @param SearchCriteriaBuilder $searchCriteriaBuilder
      */
     public function __construct(
         TaxRuleBuilder $taxRuleBuilder,
         TaxRuleConverter $converter,
         TaxRuleRegistry $taxRuleRegistry,
         Data\TaxRuleSearchResultsBuilder $taxRuleSearchResultsBuilder,
-        TaxRuleModelFactory $taxRuleModelFactory
+        TaxRuleModelFactory $taxRuleModelFactory,
+        FilterBuilder $filterBuilder,
+        TaxRateServiceInterface $taxRateService,
+        SearchCriteriaBuilder $searchCriteriaBuilder
     ) {
         $this->taxRuleBuilder = $taxRuleBuilder;
         $this->converter = $converter;
         $this->taxRuleRegistry = $taxRuleRegistry;
         $this->taxRuleSearchResultsBuilder = $taxRuleSearchResultsBuilder;
         $this->taxRuleModelFactory = $taxRuleModelFactory;
+        $this->filterBuilder = $filterBuilder;
+        $this->taxRateService = $taxRateService;
+        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
     }
 
     /**
@@ -139,16 +165,27 @@ class TaxRuleService implements TaxRuleServiceInterface
         $this->taxRuleSearchResultsBuilder->setSearchCriteria($searchCriteria);
         $collection = $this->taxRuleModelFactory->create()->getCollection();
 
+        $fields = [];
+
         //Add filters from root filter group to the collection
         foreach ($searchCriteria->getFilterGroups() as $group) {
             $this->addFilterGroupToCollection($group, $collection);
+            foreach ($group->getFilters() as $filter) {
+                $fields[] = $this->translateField($filter->getField());
+            }
+        }
+        if ($fields) {
+            if (in_array('cd.customer_tax_class_id', $fields) || in_array('cd.product_tax_class_id', $fields)) {
+                $collection->joinCalculationData('cd');
+            }
         }
+
         $this->taxRuleSearchResultsBuilder->setTotalCount($collection->getSize());
         $sortOrders = $searchCriteria->getSortOrders();
         if ($sortOrders) {
-            foreach ($sortOrders as $field => $direction) {
-                $field = $this->translateField($field);
-                $collection->addOrder($field, $direction == SearchCriteria::SORT_ASC ? 'ASC' : 'DESC');
+            foreach ($sortOrders as $sortField => $direction) {
+                $sortField = $this->translateField($sortField);
+                $collection->addOrder($sortField, $direction == SearchCriteria::SORT_ASC ? 'ASC' : 'DESC');
             }
         }
         $collection->setCurPage($searchCriteria->getCurrentPage());
@@ -165,6 +202,44 @@ class TaxRuleService implements TaxRuleServiceInterface
         return $this->taxRuleSearchResultsBuilder->create();
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    public function getRatesByCustomerAndProductTaxClassId($customerTaxClassId, $productTaxClassId)
+    {
+        $this->searchCriteriaBuilder->addFilter(
+            [
+                $this->filterBuilder
+                    ->setField(TaxRule::CUSTOMER_TAX_CLASS_IDS)
+                    ->setValue([$customerTaxClassId])
+                    ->create(),
+            ]
+        );
+
+        $this->searchCriteriaBuilder->addFilter(
+            [
+                $this->filterBuilder
+                    ->setField(TaxRule::PRODUCT_TAX_CLASS_IDS)
+                    ->setValue([$productTaxClassId])
+                    ->create(),
+            ]
+        );
+
+
+        $searchResults = $this->searchTaxRules($this->searchCriteriaBuilder->create());
+        $taxRules = $searchResults->getItems();
+        $rates = [];
+        foreach ($taxRules as $taxRule) {
+            $rateIds = $taxRule->getTaxRateIds();
+            if (!empty($rateIds)) {
+                foreach ($rateIds as $rateId) {
+                    $rates[] = $this->taxRateService->getTaxRate($rateId);
+                }
+            }
+        }
+        return $rates;
+    }
+
     /**
      * Helper function that adds a FilterGroup to the collection.
      *
@@ -212,6 +287,12 @@ class TaxRuleService implements TaxRuleServiceInterface
         switch ($field) {
             case TaxRule::ID:
                 return 'tax_calculation_rule_id';
+            case TaxRule::TAX_RATE_IDS:
+                return 'tax_calculation_rate_id';
+            case TaxRule::CUSTOMER_TAX_CLASS_IDS:
+                return 'cd.customer_tax_class_id';
+            case TaxRule::PRODUCT_TAX_CLASS_IDS:
+                return 'cd.product_tax_class_id';
             case TaxRule::SORT_ORDER:
                 return 'position';
             default:
@@ -258,6 +339,10 @@ class TaxRuleService implements TaxRuleServiceInterface
     {
         $exception = new InputException();
 
+        // SortOrder is required and must be 0 or greater
+        if (!\Zend_Validate::is(trim($rule->getSortOrder()), 'NotEmpty')) {
+            $exception->addError(InputException::REQUIRED_FIELD, ['fieldName' => TaxRule::SORT_ORDER]);
+        }
         if (!\Zend_Validate::is(trim($rule->getSortOrder()), 'GreaterThan', [-1])) {
             $exception->addError(
                 InputException::INVALID_FIELD_MIN_VALUE,
@@ -265,6 +350,10 @@ class TaxRuleService implements TaxRuleServiceInterface
             );
         }
 
+        // Priority is required and must be 0 or greater
+        if (!\Zend_Validate::is(trim($rule->getPriority()), 'NotEmpty')) {
+            $exception->addError(InputException::REQUIRED_FIELD, ['fieldName' => TaxRule::PRIORITY]);
+        }
         if (!\Zend_Validate::is(trim($rule->getPriority()), 'GreaterThan', [-1])) {
             $exception->addError(
                 InputException::INVALID_FIELD_MIN_VALUE,
diff --git a/app/code/Magento/Tax/Service/V1/TaxRuleServiceInterface.php b/app/code/Magento/Tax/Service/V1/TaxRuleServiceInterface.php
index 7f031b65a0c6a6f35d784b330ab4558f2609c652..92a5f66116c78bb9193e2abb1db7e632070f5120 100644
--- a/app/code/Magento/Tax/Service/V1/TaxRuleServiceInterface.php
+++ b/app/code/Magento/Tax/Service/V1/TaxRuleServiceInterface.php
@@ -76,4 +76,13 @@ interface TaxRuleServiceInterface
      * @throws \Magento\Framework\Exception\InputException If there is a problem with the input
      */
     public function searchTaxRules(\Magento\Framework\Service\V1\Data\SearchCriteria $searchCriteria);
+
+    /**
+     * Get rates by customerTaxClassId and productTaxClassId
+     *
+     * @param int $customerTaxClassId
+     * @param int $productTaxClassId
+     * @return \Magento\Tax\Service\V1\Data\TaxRate[]
+     */
+    public function getRatesByCustomerAndProductTaxClassId($customerTaxClassId, $productTaxClassId);
 }
diff --git a/app/code/Magento/Tax/etc/module.xml b/app/code/Magento/Tax/etc/module.xml
index 45ddd128035b102f7077c85966969e88c70b0e4d..1d69d97aeef6479dc64450cab358d7f6863c37d4 100644
--- a/app/code/Magento/Tax/etc/module.xml
+++ b/app/code/Magento/Tax/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Tax" schema_version="1.6.0.6" active="true">
+    <module name="Magento_Tax" schema_version="1.6.0.7" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
             <module name="Magento_Customer"/>
diff --git a/app/code/Magento/Tax/etc/webapi.xml b/app/code/Magento/Tax/etc/webapi.xml
index 84934d0208507f9b8a3240b95f865f3a0982dc84..24fd425954f18db87ef201eb5ae47b676be7359f 100644
--- a/app/code/Magento/Tax/etc/webapi.xml
+++ b/app/code/Magento/Tax/etc/webapi.xml
@@ -49,6 +49,12 @@
             <resource ref="Magento_Tax::manage_tax"/>
         </resources>
     </route>
+    <route url="/V1/taxRate/search" method="PUT">
+        <service class="Magento\Tax\Service\V1\TaxRateServiceInterface" method="searchTaxRates"/>
+        <resources>
+            <resource ref="Magento_Tax::manage_tax"/>
+        </resources>
+    </route>
     <route url="/V1/taxRules" method="POST">
         <service class="Magento\Tax\Service\V1\TaxRuleServiceInterface" method="createTaxRule"/>
         <resources>
diff --git a/app/code/Magento/Tax/sql/tax_setup/install-1.6.0.0.php b/app/code/Magento/Tax/sql/tax_setup/install-1.6.0.0.php
index dd256acaf2396b63dd093a1192793bbd20552985..446d00f7ac5556bc1dac827f51c7af5b8121c79b 100644
--- a/app/code/Magento/Tax/sql/tax_setup/install-1.6.0.0.php
+++ b/app/code/Magento/Tax/sql/tax_setup/install-1.6.0.0.php
@@ -418,11 +418,11 @@ $catalogInstaller->addAttribute(
         'required' => true,
         'user_defined' => false,
         'default' => '',
-        'searchable' => true,
+        'searchable' => false,
         'filterable' => false,
         'comparable' => false,
         'visible_on_front' => false,
-        'visible_in_advanced_search' => true,
+        'visible_in_advanced_search' => false,
         'used_in_product_listing' => true,
         'unique' => false,
         'apply_to' => implode($this->getTaxableItems(), ',')
diff --git a/app/code/Magento/Tax/sql/tax_setup/upgrade-1.6.0.6-1.6.0.7.php b/app/code/Magento/Tax/sql/tax_setup/upgrade-1.6.0.6-1.6.0.7.php
new file mode 100644
index 0000000000000000000000000000000000000000..ee47d2d995693616ac86b72585e7e6ffc2b4f424
--- /dev/null
+++ b/app/code/Magento/Tax/sql/tax_setup/upgrade-1.6.0.6-1.6.0.7.php
@@ -0,0 +1,113 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/** @var \Magento\Tax\Model\Resource\Setup $installer */
+$installer = $this;
+$connection = $installer->getConnection();
+
+/**
+ * Add new field to 'sales_order_tax_item'
+ */
+$connection->addColumn(
+    $installer->getTable('sales_order_tax_item'),
+    'amount',
+    [
+        'TYPE' => \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL,
+        'SCALE' => 4,
+        'PRECISION' => 12,
+        'NULLABLE' => false,
+        'COMMENT' => 'Tax amount for the item and tax rate.'
+    ]
+);
+$connection->addColumn(
+    $installer->getTable('sales_order_tax_item'),
+    'base_amount',
+    [
+        'TYPE' => \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL,
+        'SCALE' => 4,
+        'PRECISION' => 12,
+        'NULLABLE' => false,
+        'COMMENT' => 'Base tax amount for the item and tax rate.'
+    ]
+);
+$connection->addColumn(
+    $installer->getTable('sales_order_tax_item'),
+    'real_amount',
+    [
+        'TYPE' => \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL,
+        'SCALE' => 4,
+        'PRECISION' => 12,
+        'NULLABLE' => false,
+        'COMMENT' => 'Real tax amount for the item and tax rate.'
+    ]
+);
+$connection->addColumn(
+    $installer->getTable('sales_order_tax_item'),
+    'real_base_amount',
+    [
+        'TYPE' => \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL,
+        'SCALE' => 4,
+        'PRECISION' => 12,
+        'NULLABLE' => false,
+        'COMMENT' => 'Real base tax amount for the item and tax rate.'
+    ]
+);
+$connection->addColumn(
+    $installer->getTable('sales_order_tax_item'),
+    'associated_item_id',
+    [
+        'TYPE' => \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
+        'UNSIGNED' => true,
+        'NULLABLE' => true,
+        'COMMENT' => 'Id of the associated item.'
+    ]
+);
+$connection->addColumn(
+    $installer->getTable('sales_order_tax_item'),
+    'taxable_item_type',
+    [
+        'TYPE' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
+        'length' => 32,
+        'NULLABLE' => false,
+        'COMMENT' => 'Type of the taxable item.'
+    ]
+);
+$connection->changeColumn(
+    $installer->getTable('sales_order_tax_item'),
+    'item_id',
+    'item_id',
+    [
+        'TYPE' => \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
+        'NULLABLE' => true,
+        'UNSIGNED' => true,
+        'COMMENT' => 'Item Id',
+    ]
+);
+$connection->addForeignKey(
+    $installer->getFkName('sales_order_tax_item', 'associated_item_id', 'sales_flat_order_item', 'item_id'),
+    $installer->getTable('sales_order_tax_item'),
+    'associated_item_id',
+    $installer->getTable('sales_flat_order_item'),
+    'item_id'
+);
diff --git a/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_block.xml b/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_block.xml
index 80a0368ed5665c54a0b7c2544f314873e5ff3634..b3909d69eb580319914779410561a6d26f307c0a 100644
--- a/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_block.xml
+++ b/app/code/Magento/Tax/view/adminhtml/layout/tax_rate_block.xml
@@ -61,7 +61,7 @@
                     <arguments>
                         <argument name="header" xsi:type="string" translate="true">Tax Identifier</argument>
                         <argument name="header_export" xsi:type="string" translate="true">Code</argument>
-                        <argument name="filter_index" xsi:type="string">main_table.code</argument>
+                        <argument name="filter_index" xsi:type="string">code</argument>
                         <argument name="index" xsi:type="string">code</argument>
                         <argument name="column_css_class" xsi:type="string">col-name</argument>
                         <argument name="header_css_class" xsi:type="string">col-name</argument>
@@ -71,7 +71,7 @@
                     <arguments>
                         <argument name="header" xsi:type="string" translate="true">Country</argument>
                         <argument name="type" xsi:type="string">country</argument>
-                        <argument name="filter_index" xsi:type="string">main_table.tax_country_id</argument>
+                        <argument name="filter_index" xsi:type="string">tax_country_id</argument>
                         <argument name="index" xsi:type="string">tax_country_id</argument>
                         <argument name="renderer" xsi:type="string">Magento\Tax\Block\Adminhtml\Rate\Grid\Renderer\Country</argument>
                         <argument name="sortable" xsi:type="string">0</argument>
@@ -81,7 +81,7 @@
                     <arguments>
                         <argument name="header" xsi:type="string" translate="true">State/Region</argument>
                         <argument name="header_export" xsi:type="string" translate="true">State</argument>
-                        <argument name="filter_index" xsi:type="string">region_table.code</argument>
+                        <argument name="filter_index" xsi:type="string">region_name</argument>
                         <argument name="index" xsi:type="string">region_name</argument>
                         <argument name="default" xsi:type="string">*</argument>
                     </arguments>
diff --git a/app/code/Magento/Tax/view/frontend/templates/checkout/tax.phtml b/app/code/Magento/Tax/view/frontend/templates/checkout/tax.phtml
index f89e769ac0d7f51d1b647779693c47d9f2851df4..9bc2d80357614dfbe57961b48a3c314b9bdc4ea9 100644
--- a/app/code/Magento/Tax/view/frontend/templates/checkout/tax.phtml
+++ b/app/code/Magento/Tax/view/frontend/templates/checkout/tax.phtml
@@ -31,39 +31,11 @@
     $_style = $this->getTotal()->getStyle();
 ?>
 <?php global $taxIter; $taxIter++; ?>
-<?php if ($this->helper('Magento\Tax\Helper\Data')->displayFullSummary() && $_value!=0): ?>
-<?php $isTop = 1; ?>
-    <?php foreach ($this->getTotal()->getFullInfo() as $info): ?>
-        <?php if (isset($info['hidden']) && $info['hidden']) continue; ?>
-        <?php $percent = $info['percent']; ?>
-        <?php $amount = $info['amount']; ?>
-        <?php $rates = $info['rates']; ?>
-        <?php $isFirst = 1; ?>
 
-        <?php foreach ($rates as $rate): ?>
-        <tr class="totals tax details details-<?php echo $taxIter; ?>">
-            <td class="mark" style="<?php echo $_style ?>" colspan="<?php echo $this->getColspan(); ?>">
-                <?php echo $this->escapeHtml($rate['title']); ?>
-                <?php if (!is_null($rate['percent'])): ?>
-                    (<?php echo (float)$rate['percent']; ?>%)
-                <?php endif; ?>
-                <br />
-            </td>
-            <?php if ($isFirst): ?>
-                <td style="<?php echo $_style ?>" class="amount" rowspan="<?php echo count($rates); ?>">
-                    <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($amount); ?>
-                </td>
-            <?php endif; ?>
-        </tr>
-        <?php $isFirst = 0; ?>
-        <?php $isTop = 0; ?>
-        <?php endforeach; ?>
-    <?php endforeach; ?>
-<?php endif;?>
 <?php
-    $attributes = 'class="totals tax"';
+    $attributes = 'class="totals-tax"';
     if ($this->helper('Magento\Tax\Helper\Data')->displayFullSummary() && $_value!=0) {
-        $attributes = 'class="totals tax summary" data-mage-init=\'{"toggleAdvanced": {"selectorsToggleClass": "shown", "baseToggleClass": "expanded", "toggleContainers": ".totals.tax.details"}}\'';
+        $attributes = 'class="totals-tax-summary" data-mage-init=\'{"toggleAdvanced": {"selectorsToggleClass": "shown", "baseToggleClass": "expanded", "toggleContainers": ".totals-tax-details"}}\'';
     }
 ?>
 
@@ -77,3 +49,33 @@
     </td>
     <td style="<?php echo $_style ?>" class="amount"><?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($_value) ?></td>
 </tr>
+
+<?php if ($this->helper('Magento\Tax\Helper\Data')->displayFullSummary() && $_value!=0): ?>
+    <?php $isTop = 1; ?>
+    <?php foreach ($this->getTotal()->getFullInfo() as $info): ?>
+        <?php if (isset($info['hidden']) && $info['hidden']) continue; ?>
+        <?php $percent = $info['percent']; ?>
+        <?php $amount = $info['amount']; ?>
+        <?php $rates = $info['rates']; ?>
+        <?php $isFirst = 1; ?>
+
+        <?php foreach ($rates as $rate): ?>
+            <tr class="totals-tax-details details-<?php echo $taxIter; ?>">
+                <td class="mark" style="<?php echo $_style ?>" colspan="<?php echo $this->getColspan(); ?>">
+                    <?php echo $this->escapeHtml($rate['title']); ?>
+                    <?php if (!is_null($rate['percent'])): ?>
+                        (<?php echo (float)$rate['percent']; ?>%)
+                    <?php endif; ?>
+                    <br />
+                </td>
+                <?php if ($isFirst): ?>
+                    <td style="<?php echo $_style ?>" class="amount" rowspan="<?php echo count($rates); ?>">
+                        <?php echo $this->helper('Magento\Checkout\Helper\Data')->formatPrice($amount); ?>
+                    </td>
+                <?php endif; ?>
+            </tr>
+            <?php $isFirst = 0; ?>
+            <?php $isTop = 0; ?>
+        <?php endforeach; ?>
+    <?php endforeach; ?>
+<?php endif;?>
diff --git a/app/code/Magento/Tax/view/frontend/templates/order/tax.phtml b/app/code/Magento/Tax/view/frontend/templates/order/tax.phtml
index 21593380d2425db4bad49d8032f5a46e567027c3..cf069d794c268850213777051cdc27a3c92dac31 100644
--- a/app/code/Magento/Tax/view/frontend/templates/order/tax.phtml
+++ b/app/code/Magento/Tax/view/frontend/templates/order/tax.phtml
@@ -41,7 +41,7 @@
         ?>
         <?php foreach ($rates as $rate): ?>
         <tr class="totals tax details details-<?php echo $taxIter; ?> <?php echo ($this->getIsPlaneMode()) ? ' plane' : '';?>">
-            <td class="mark" <?php echo $this->getLabelProperties()?>>
+            <td <?php echo $this->getLabelProperties()?>>
                 <?php echo $this->escapeHtml($rate['title']); ?>
                 <?php if (!is_null($rate['percent'])): ?>
                     (<?php echo (float)$rate['percent']; ?>%)
@@ -49,7 +49,7 @@
                 <br />
             </td>
             <?php if ($isFirst): ?>
-                <td class="amount" <?php echo $this->getValueProperties()?> rowspan="<?php echo count($rates); ?>">
+                <td <?php echo $this->getValueProperties()?> rowspan="<?php echo count($rates); ?>">
                     <?php echo $_order->formatPrice($amount); ?>
                 </td>
             <?php endif; ?>
@@ -61,18 +61,18 @@
 <?php endif;?>
 
 <?php if ($this->displayFullSummary() && $_fullInfo && !$this->getIsPlaneMode()): ?>
-<tr class="totals tax summary">
+<tr class="totals-tax-summary">
 <?php elseif ($this->displayFullSummary() && $_fullInfo && $this->getIsPlaneMode()): ?>
-<tr class="totals tax summary plane">
+<tr class="totals-tax-summary plane">
 <?php else: ?>
-<tr class="totals tax">
+<tr class="totals-tax">
 <?php endif; ?>
-    <td class="mark" <?php echo $this->getLabelProperties()?>>
+    <td <?php echo $this->getLabelProperties()?>>
         <?php if ($this->displayFullSummary()): ?>
             <div class="detailed"><?php echo __('Tax'); ?></div>
         <?php else: ?>
             <?php echo __('Tax'); ?>
         <?php endif;?>
     </td>
-    <td class="amount" <?php echo $this->getValueProperties()?>><?php echo $_order->formatPrice($_source->getTaxAmount()) ?></td>
+    <td <?php echo $this->getValueProperties()?>><?php echo $_order->formatPrice($_source->getTaxAmount()) ?></td>
 </tr>
diff --git a/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml b/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml
index 5f825917ac5ac9d9294386b71e44f0be53d2e919..b041e7e658e6f4d7d273cf5569eb7a89abf6dd12 100644
--- a/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml
+++ b/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml
@@ -51,6 +51,11 @@
                 <argument name="file" xsi:type="string">mage/jquery-no-conflict.js</argument>
             </arguments>
         </block>
+        <block class="Magento\Theme\Block\Html\Head\Script" name="jquery-mobile-custom-js">
+            <arguments>
+                <argument name="file" xsi:type="string">jquery/jquery.mobile.custom.js</argument>
+            </arguments>
+        </block>
         <block class="Magento\Theme\Block\Html\Head\Script" name="js-head-js">
             <arguments>
                 <argument name="file" xsi:type="string">headjs/head.min.js</argument>
diff --git a/app/code/Magento/Theme/view/frontend/templates/html/pager.phtml b/app/code/Magento/Theme/view/frontend/templates/html/pager.phtml
index 8ed2a090f765c63d6fc27bc4b9e66e50492a3e9c..85171d2ccfe9e8b2c41b7ed01f3b647f31328152 100644
--- a/app/code/Magento/Theme/view/frontend/templates/html/pager.phtml
+++ b/app/code/Magento/Theme/view/frontend/templates/html/pager.phtml
@@ -35,39 +35,26 @@
     <div class="pager">
     <?php endif ?>
 
-    <?php if($this->getShowAmounts()): ?>
-    <p class="amount">
-        <?php if($this->getLastPageNum()>1): ?>
-            <?php echo __('Items %1 to %2 of %3 total', $this->getFirstNum(), $this->getLastNum(), $this->getTotalNum()) ?>
-        <?php elseif ($this->getLastPageNum() == 1): ?>
-            <?php echo __('%1 Item', $this->getTotalNum()) ?>
-        <?php else: ?>
-            <?php echo __('%1 Item(s)', $this->getTotalNum()) ?>
-        <?php endif; ?>
-    </p>
-    <?php endif ?>
-
-        <?php if($this->isShowPerPage()): ?>
-            <div class="limiter">
-                <strong class="label"><?php echo __('Show') ?></strong>
-                <select id="limiter" data-mage-redirect="{'event':'change'}">
-                    <?php foreach ($this->getAvailableLimit() as $_key => $_limit): ?>
-                    <option value="<?php echo $this->getLimitUrl($_key) ?>"<?php if ($this->isLimitCurrent($_key)): ?>
-                            selected="selected"<?php endif ?>>
-                        <?php echo $_limit ?>
-                    </option>
-                    <?php endforeach; ?>
-                </select>
-                <span class="text"><?php echo __('per page') ?></span>
-            </div>
+        <?php if($this->getShowAmounts()): ?>
+        <p class="toolbar-amount">
+            <span class="toolbar-number">
+            <?php if($this->getLastPageNum()>1): ?>
+                <?php echo __('Items %1 to %2 of %3 total', $this->getFirstNum(), $this->getLastNum(), $this->getTotalNum()) ?>
+            <?php elseif ($this->getLastPageNum() == 1): ?>
+                <?php echo __('%1 Item', $this->getTotalNum()) ?>
+            <?php else: ?>
+                <?php echo __('%1 Item(s)', $this->getTotalNum()) ?>
+            <?php endif; ?>
+            </span>
+        </p>
         <?php endif ?>
 
         <?php if($this->getLastPageNum()>1): ?>
         <div class="pages">
-            <strong class="label" id="paging-label"><?php echo __('Page') ?></strong>
-            <ul class="items" aria-labelledby="paging-label">
+            <strong class="label pages-label" id="paging-label"><?php echo __('Page') ?></strong>
+            <ul class="items pages-items" aria-labelledby="paging-label">
             <?php if (!$this->isFirstPage()): ?>
-                <li class="item">
+                <li class="item pages-item-previous">
                     <?php $text = $this->getAnchorTextForPrevious() ? $this->getAnchorTextForPrevious() : '';?>
                     <a class="<?php echo $text ? 'link ' : 'action '?> previous" href="<?php echo $this->getPreviousPageUrl() ?>" title="<?php echo $text ? $text : __('Previous') ?>">
                         <span class="label"><?php echo __('Page') ?></span>
@@ -129,7 +116,7 @@
             <?php endif;?>
 
             <?php if (!$this->isLastPage()): ?>
-                <li class="item">
+                <li class="item pages-item-next">
                     <?php $text = $this->getAnchorTextForNext() ? $this->getAnchorTextForNext() : '';?>
                     <a class="<?php echo $text ? 'link ' : 'action '?> next" href="<?php echo $this->getNextPageUrl() ?>" title="<?php echo $text ? $text : __('Next') ?>">
                         <span class="label"><?php echo __('Page') ?></span>
@@ -141,6 +128,21 @@
         </div>
         <?php endif; ?>
 
+        <?php if($this->isShowPerPage()): ?>
+            <div class="limiter">
+                <strong class="limiter-label"><?php echo __('Show') ?></strong>
+                <select id="limiter" data-mage-redirect="{'event':'change'}" class="limiter-options">
+                    <?php foreach ($this->getAvailableLimit() as $_key => $_limit): ?>
+                    <option value="<?php echo $this->getLimitUrl($_key) ?>"<?php if ($this->isLimitCurrent($_key)): ?>
+                            selected="selected"<?php endif ?>>
+                        <?php echo $_limit ?>
+                    </option>
+                    <?php endforeach; ?>
+                </select>
+                <span class="limiter-text"><?php echo __('per page') ?></span>
+            </div>
+        <?php endif ?>
+
     <?php if($this->getUseContainer()): ?>
     </div>
     <?php endif ?>
diff --git a/app/code/Magento/Translation/Model/Js/DataProvider.php b/app/code/Magento/Translation/Model/Js/DataProvider.php
index 2908b845229328c779c983644e66821fe70eaf5b..6dc3e5edbcbfe6d958814edabe8797aaee1ee18d 100644
--- a/app/code/Magento/Translation/Model/Js/DataProvider.php
+++ b/app/code/Magento/Translation/Model/Js/DataProvider.php
@@ -175,6 +175,7 @@ class DataProvider implements DataProviderInterface
             'Ok' => __('Ok'),
             'Please specify at least one search term.' => __('Please specify at least one search term.'),
             'Create New Wish List' => __('Create New Wish List'),
+            'Click Details for more required fields.' => __('Click Details for more required fields.'),
         );
     }
 }
diff --git a/app/code/Magento/Translation/Model/Resource/Translate.php b/app/code/Magento/Translation/Model/Resource/Translate.php
index 3cf0b2bccead154fc40ecced3301294a9ea0b8a9..180e00f407106dcd975c691ceea579040e304712 100644
--- a/app/code/Magento/Translation/Model/Resource/Translate.php
+++ b/app/code/Magento/Translation/Model/Resource/Translate.php
@@ -90,16 +90,11 @@ class Translate extends \Magento\Framework\Model\Resource\Db\AbstractDb implemen
             return array();
         }
 
-        $select = $adapter->select()->from(
-            $this->getMainTable(),
-            array('string', 'translate')
-        )->where(
-            'store_id IN (0 , :store_id)'
-        )->where(
-            'locale = :locale'
-        )->order(
-            'store_id'
-        );
+        $select = $adapter->select()
+            ->from($this->getMainTable(), array('string', 'translate'))
+            ->where('store_id IN (0 , :store_id)')
+            ->where('locale = :locale')
+            ->order('store_id');
 
         $bind = array(':locale' => (string)$locale, ':store_id' => $storeId);
 
@@ -133,15 +128,10 @@ class Translate extends \Magento\Framework\Model\Resource\Db\AbstractDb implemen
         }
 
         $bind = array(':store_id' => $storeId);
-        $select = $adapter->select()->from(
-            $this->getMainTable(),
-            array('string', 'translate')
-        )->where(
-            'string IN (?)',
-            $strings
-        )->where(
-            'store_id = :store_id'
-        );
+        $select = $adapter->select()
+            ->from($this->getMainTable(), array('string', 'translate'))
+            ->where('string IN (?)', $strings)
+            ->where('store_id = :store_id');
 
         return $adapter->fetchPairs($select, $bind);
     }
diff --git a/app/code/Magento/UrlRedirect/Block/Catalog/Category/Edit.php b/app/code/Magento/UrlRedirect/Block/Catalog/Category/Edit.php
new file mode 100644
index 0000000000000000000000000000000000000000..a0316d07eafb8c7317aa8e4771493a034e55e5f2
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Block/Catalog/Category/Edit.php
@@ -0,0 +1,131 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Block\Catalog\Category;
+
+/**
+ * Block for Catalog Category URL rewrites
+ */
+class Edit extends \Magento\UrlRedirect\Block\Edit
+{
+    /**
+     * @var \Magento\Catalog\Model\CategoryFactory
+     */
+    protected $_categoryFactory;
+
+    /**
+     * @param \Magento\Backend\Block\Widget\Context $context
+     * @param \Magento\UrlRedirect\Model\UrlRedirectFactory $rewriteFactory
+     * @param \Magento\Backend\Helper\Data $adminhtmlData
+     * @param \Magento\Catalog\Model\CategoryFactory $categoryFactory
+     * @param array $data
+     */
+    public function __construct(
+        \Magento\Backend\Block\Widget\Context $context,
+        \Magento\UrlRedirect\Model\UrlRedirectFactory $rewriteFactory,
+        \Magento\Backend\Helper\Data $adminhtmlData,
+        \Magento\Catalog\Model\CategoryFactory $categoryFactory,
+        array $data = array()
+    ) {
+        $this->_categoryFactory = $categoryFactory;
+        parent::__construct($context, $rewriteFactory, $adminhtmlData, $data);
+    }
+
+    /**
+     * Prepare layout for URL rewrite creating for category
+     *
+     * @return void
+     */
+    protected function _prepareLayoutFeatures()
+    {
+        if ($this->_getUrlRewrite()->getId()) {
+            $this->_headerText = __('Edit URL Rewrite for a Category');
+        } else {
+            $this->_headerText = __('Add URL Rewrite for a Category');
+        }
+
+        if ($this->_getCategory()->getId()) {
+            $this->_addCategoryLinkBlock();
+            $this->_addEditFormBlock();
+            $this->_updateBackButtonLink($this->_adminhtmlData->getUrl('adminhtml/*/edit') . 'category');
+        } else {
+            $this->_addUrlRewriteSelectorBlock();
+            $this->_addCategoryTreeBlock();
+        }
+    }
+
+    /**
+     * Get or create new instance of category
+     *
+     * @return \Magento\Catalog\Model\Product
+     */
+    private function _getCategory()
+    {
+        if (!$this->hasData('category')) {
+            $this->setCategory($this->_categoryFactory->create());
+        }
+        return $this->getCategory();
+    }
+
+    /**
+     * Add child category link block
+     *
+     * @return void
+     */
+    private function _addCategoryLinkBlock()
+    {
+        $this->addChild(
+            'category_link',
+            'Magento\UrlRedirect\Block\Link',
+            array(
+                'item_url' => $this->_adminhtmlData->getUrl('adminhtml/*/*') . 'category',
+                'item_name' => $this->_getCategory()->getName(),
+                'label' => __('Category:')
+            )
+        );
+    }
+
+    /**
+     * Add child category tree block
+     *
+     * @return void
+     */
+    private function _addCategoryTreeBlock()
+    {
+        $this->addChild('categories_tree', 'Magento\UrlRedirect\Block\Catalog\Category\Tree');
+    }
+
+    /**
+     * Creates edit form block
+     *
+     * @return \Magento\UrlRedirect\Block\Catalog\Edit\Form
+     */
+    protected function _createEditFormBlock()
+    {
+        return $this->getLayout()->createBlock(
+            'Magento\UrlRedirect\Block\Catalog\Edit\Form',
+            '',
+            array('data' => array('category' => $this->_getCategory(), 'url_rewrite' => $this->_getUrlRewrite()))
+        );
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Block/Catalog/Category/Tree.php b/app/code/Magento/UrlRedirect/Block/Catalog/Category/Tree.php
new file mode 100644
index 0000000000000000000000000000000000000000..4032848799915ef11e5739579024931869440bad
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Block/Catalog/Category/Tree.php
@@ -0,0 +1,196 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Block\Catalog\Category;
+
+/**
+ * Categories tree block for URL rewrites editing process
+ *
+ * @author     Magento Core Team <core@magentocommerce.com>
+ */
+class Tree extends \Magento\Catalog\Block\Adminhtml\Category\AbstractCategory
+{
+    /**
+     * List of allowed category ids
+     *
+     * @var int[]|null
+     */
+    protected $_allowedCategoryIds = null;
+
+    /**
+     * @var string
+     */
+    protected $_template = 'categories.phtml';
+
+    /**
+     * Adminhtml data
+     *
+     * @var \Magento\Backend\Helper\Data
+     */
+    protected $_adminhtmlData = null;
+
+    /**
+     * @var \Magento\Catalog\Model\CategoryFactory
+     */
+    protected $_categoryFactory;
+
+    /**
+     * @var \Magento\Catalog\Model\ProductFactory
+     */
+    protected $_productFactory;
+
+    /**
+     * @var \Magento\Framework\Json\EncoderInterface
+     */
+    protected $_jsonEncoder;
+
+    /**
+     * @param \Magento\Backend\Block\Widget\Context $context
+     * @param \Magento\Catalog\Model\Resource\Category\Tree $categoryTree
+     * @param \Magento\Framework\Registry $registry
+     * @param \Magento\Framework\Json\EncoderInterface $jsonEncoder
+     * @param \Magento\Catalog\Model\ProductFactory $productFactory
+     * @param \Magento\Catalog\Model\CategoryFactory $categoryFactory
+     * @param \Magento\Backend\Helper\Data $adminhtmlData
+     * @param array $data
+     */
+    public function __construct(
+        \Magento\Backend\Block\Widget\Context $context,
+        \Magento\Catalog\Model\Resource\Category\Tree $categoryTree,
+        \Magento\Framework\Registry $registry,
+        \Magento\Catalog\Model\CategoryFactory $categoryFactory,
+        \Magento\Framework\Json\EncoderInterface $jsonEncoder,
+        \Magento\Catalog\Model\ProductFactory $productFactory,
+        \Magento\Backend\Helper\Data $adminhtmlData,
+        array $data = array()
+    ) {
+        $this->_jsonEncoder = $jsonEncoder;
+        $this->_categoryFactory = $categoryFactory;
+        $this->_productFactory = $productFactory;
+        $this->_adminhtmlData = $adminhtmlData;
+        parent::__construct($context, $categoryTree, $registry, $categoryFactory, $data);
+    }
+
+    /**
+     * Get categories tree as recursive array
+     *
+     * @param int $parentId
+     * @param bool $asJson
+     * @param int $recursionLevel
+     * @return array
+     */
+    public function getTreeArray($parentId = null, $asJson = false, $recursionLevel = 3)
+    {
+        $productId = $this->_request->getParam('product');
+        if ($productId) {
+            $product = $this->_productFactory->create()->setId($productId);
+            $this->_allowedCategoryIds = $product->getCategoryIds();
+            unset($product);
+        }
+
+        $result = array();
+        if ($parentId) {
+            $category = $this->_categoryFactory->create()->load($parentId);
+            if (!empty($category)) {
+                $tree = $this->_getNodesArray($this->getNode($category, $recursionLevel));
+                if (!empty($tree) && !empty($tree['children'])) {
+                    $result = $tree['children'];
+                }
+            }
+        } else {
+            $result = $this->_getNodesArray($this->getRoot(null, $recursionLevel));
+        }
+
+        if ($asJson) {
+            return $this->_jsonEncoder->encode($result);
+        }
+
+        $this->_allowedCategoryIds = null;
+
+        return $result;
+    }
+
+    /**
+     * Get categories collection
+     *
+     * @return \Magento\Catalog\Model\Resource\Category\Collection
+     */
+    public function getCategoryCollection()
+    {
+        $collection = $this->_getData('category_collection');
+        if (is_null($collection)) {
+            $collection = $this->_categoryFactory->create()->getCollection()->addAttributeToSelect(
+                array('name', 'is_active')
+            )->setLoadProductCount(
+                true
+            );
+            $this->setData('category_collection', $collection);
+        }
+
+        return $collection;
+    }
+
+    /**
+     * Convert categories tree to array recursively
+     *
+     * @param  \Magento\Framework\Data\Tree\Node $node
+     * @return array
+     */
+    protected function _getNodesArray($node)
+    {
+        $result = array(
+            'id' => (int)$node->getId(),
+            'parent_id' => (int)$node->getParentId(),
+            'children_count' => (int)$node->getChildrenCount(),
+            'is_active' => (bool)$node->getIsActive(),
+            'name' => $node->getName(),
+            'level' => (int)$node->getLevel(),
+            'product_count' => (int)$node->getProductCount()
+        );
+
+        if (is_array($this->_allowedCategoryIds) && !in_array($result['id'], $this->_allowedCategoryIds)) {
+            $result['disabled'] = true;
+        }
+
+        if ($node->hasChildren()) {
+            $result['children'] = array();
+            foreach ($node->getChildren() as $childNode) {
+                $result['children'][] = $this->_getNodesArray($childNode);
+            }
+        }
+        $result['cls'] = ($result['is_active'] ? '' : 'no-') . 'active-category';
+        $result['expanded'] = !empty($result['children']);
+
+        return $result;
+    }
+
+    /**
+     * Get URL for categories tree ajax loader
+     *
+     * @return string
+     */
+    public function getLoadTreeUrl()
+    {
+        return $this->_adminhtmlData->getUrl('adminhtml/*/categoriesJson');
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Block/Catalog/Edit/Form.php b/app/code/Magento/UrlRedirect/Block/Catalog/Edit/Form.php
new file mode 100644
index 0000000000000000000000000000000000000000..0875908a272676c642eb2f4bf6bd4d1e2e215703
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Block/Catalog/Edit/Form.php
@@ -0,0 +1,222 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/**
+ * Edit form for Catalog product and category URL rewrites
+ */
+namespace Magento\UrlRedirect\Block\Catalog\Edit;
+
+use Magento\UrlRedirect\Controller\Adminhtml\UrlRedirect;
+
+/**
+ * @SuppressWarnings(PHPMD.DepthOfInheritance)
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class Form extends \Magento\UrlRedirect\Block\Edit\Form
+{
+    /**
+     * @var \Magento\Catalog\Model\Url
+     */
+    protected $_catalogUrl;
+
+    /**
+     * @var \Magento\Catalog\Model\ProductFactory
+     */
+    protected $_productFactory;
+
+    /**
+     * @var \Magento\Catalog\Model\CategoryFactory
+     */
+    protected $_categoryFactory;
+
+    /**
+     * @param \Magento\Backend\Block\Widget\Context $context
+     * @param \Magento\Framework\Registry $registry
+     * @param \Magento\Framework\Data\FormFactory $formFactory
+     * @param \Magento\UrlRedirect\Model\OptionProviderFactory $optionFactory
+     * @param \Magento\UrlRedirect\Model\UrlRedirectFactory $rewriteFactory
+     * @param \Magento\Store\Model\System\Store $systemStore
+     * @param \Magento\Backend\Helper\Data $adminhtmlData
+     * @param \Magento\Catalog\Model\ProductFactory $productFactory
+     * @param \Magento\Catalog\Model\CategoryFactory $categoryFactory
+     * @param \Magento\Catalog\Model\Url $catalogUrl
+     * @param array $data
+     *
+     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
+     */
+    public function __construct(
+        \Magento\Backend\Block\Widget\Context $context,
+        \Magento\Framework\Registry $registry,
+        \Magento\Framework\Data\FormFactory $formFactory,
+        \Magento\UrlRedirect\Model\OptionProviderFactory $optionFactory,
+        \Magento\UrlRedirect\Model\UrlRedirectFactory $rewriteFactory,
+        \Magento\Store\Model\System\Store $systemStore,
+        \Magento\Backend\Helper\Data $adminhtmlData,
+        \Magento\Catalog\Model\ProductFactory $productFactory,
+        \Magento\Catalog\Model\CategoryFactory $categoryFactory,
+        \Magento\Catalog\Model\Url $catalogUrl,
+        array $data = array()
+    ) {
+        $this->_productFactory = $productFactory;
+        $this->_categoryFactory = $categoryFactory;
+        $this->_catalogUrl = $catalogUrl;
+        parent::__construct(
+            $context,
+            $registry,
+            $formFactory,
+            $optionFactory,
+            $rewriteFactory,
+            $systemStore,
+            $adminhtmlData,
+            $data
+        );
+    }
+
+    /**
+     * Form post init
+     *
+     * @param \Magento\Framework\Data\Form $form
+     * @return $this
+     */
+    protected function _formPostInit($form)
+    {
+        $form->setAction(
+            $this->_adminhtmlData->getUrl(
+                'adminhtml/*/save',
+                array(
+                    'id' => $this->_getModel()->getId(),
+                    'product' => $this->_getProduct()->getId(),
+                    'category' => $this->_getCategory()->getId()
+                )
+            )
+        );
+
+        /** @var $requestPath \Magento\Framework\Data\Form\Element\AbstractElement */
+        $requestPath = $this->getForm()->getElement('request_path');
+        /** @var $targetPath \Magento\Framework\Data\Form\Element\AbstractElement */
+        $targetPath = $this->getForm()->getElement('target_path');
+
+        $model = $this->_getModel();
+        $disablePaths = false;
+        if (!$model->getId()) {
+            $product = null;
+            $category = null;
+            if ($this->_getProduct()->getId()) {
+                $product = $this->_getProduct();
+                $category = $this->_getCategory();
+            } elseif ($this->_getCategory()->getId()) {
+                $category = $this->_getCategory();
+            }
+
+            if ($product || $category) {
+                $sessionData = $this->_getSessionData();
+                if (!isset($sessionData['request_path'])) {
+                    $requestPath->setValue($this->_catalogUrl->generatePath('request', $product, $category, ''));
+                }
+                $targetPath->setValue($this->_catalogUrl->generatePath('target', $product, $category));
+                $disablePaths = true;
+            }
+        } else {
+            $disablePaths = in_array(
+                $model->getEntityType(),
+                [UrlRedirect::ENTITY_TYPE_PRODUCT, UrlRedirect::ENTITY_TYPE_CATEGORY, UrlRedirect::ENTITY_TYPE_CMS_PAGE]
+            );
+        }
+
+        if ($disablePaths) {
+            $targetPath->setData('disabled', true);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Get catalog entity associated stores
+     *
+     * @return array
+     * @throws \Magento\Store\Model\Exception
+     */
+    protected function _getEntityStores()
+    {
+        $product = $this->_getProduct();
+        $category = $this->_getCategory();
+        $entityStores = array();
+
+        // showing websites that only associated to products
+        if ($product->getId()) {
+            $entityStores = (array)$product->getStoreIds();
+
+            //if category is chosen, reset stores which are not related with this category
+            if ($category->getId()) {
+                $categoryStores = (array)$category->getStoreIds();
+                $entityStores = array_intersect($entityStores, $categoryStores);
+            }
+            if (!$entityStores) {
+                throw new \Magento\Store\Model\Exception(
+                    __(
+                        'We can\'t set up a URL rewrite because the product you chose is not associated with a website.'
+                    )
+                );
+            }
+            $this->_requireStoresFilter = true;
+        } elseif ($category->getId()) {
+            $entityStores = (array)$category->getStoreIds();
+            $message = __(
+                'We can\'t set up a URL rewrite because the category your chose is not associated with a website.'
+            );
+            if (!$entityStores) {
+                throw new \Magento\Store\Model\Exception($message);
+            }
+            $this->_requireStoresFilter = true;
+        }
+
+        return $entityStores;
+    }
+
+    /**
+     * Get product model instance
+     *
+     * @return \Magento\Catalog\Model\Product
+     */
+    protected function _getProduct()
+    {
+        if (!$this->hasData('product')) {
+            $this->setProduct($this->_productFactory->create());
+        }
+        return $this->getProduct();
+    }
+
+    /**
+     * Get category model instance
+     *
+     * @return \Magento\Catalog\Model\Category
+     */
+    protected function _getCategory()
+    {
+        if (!$this->hasData('category')) {
+            $this->setCategory($this->_categoryFactory->create());
+        }
+        return $this->getCategory();
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Block/Catalog/Product/Edit.php b/app/code/Magento/UrlRedirect/Block/Catalog/Product/Edit.php
new file mode 100644
index 0000000000000000000000000000000000000000..895f0a45433a7fd91153b6d3fd78302bd893060e
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Block/Catalog/Product/Edit.php
@@ -0,0 +1,230 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Block\Catalog\Product;
+
+/**
+ * Block for Catalog Category URL rewrites editing
+ */
+class Edit extends \Magento\UrlRedirect\Block\Edit
+{
+    /**
+     * @var \Magento\Catalog\Model\ProductFactory
+     */
+    protected $_productFactory;
+
+    /**
+     * @var \Magento\Catalog\Model\CategoryFactory
+     */
+    protected $_categoryFactory;
+
+    /**
+     * @param \Magento\Backend\Block\Widget\Context $context
+     * @param \Magento\UrlRedirect\Model\UrlRedirectFactory $rewriteFactory
+     * @param \Magento\Backend\Helper\Data $adminhtmlData
+     * @param \Magento\Catalog\Model\ProductFactory $productFactory
+     * @param \Magento\Catalog\Model\CategoryFactory $categoryFactory
+     * @param array $data
+     */
+    public function __construct(
+        \Magento\Backend\Block\Widget\Context $context,
+        \Magento\UrlRedirect\Model\UrlRedirectFactory $rewriteFactory,
+        \Magento\Backend\Helper\Data $adminhtmlData,
+        \Magento\Catalog\Model\ProductFactory $productFactory,
+        \Magento\Catalog\Model\CategoryFactory $categoryFactory,
+        array $data = array()
+    ) {
+        $this->_categoryFactory = $categoryFactory;
+        $this->_productFactory = $productFactory;
+        parent::__construct($context, $rewriteFactory, $adminhtmlData, $data);
+    }
+
+    /**
+     * Prepare layout for URL rewrite creating for product
+     *
+     * @return void
+     */
+    protected function _prepareLayoutFeatures()
+    {
+        if ($this->_getUrlRewrite()->getId()) {
+            $this->_headerText = __('Edit URL Rewrite for a Product');
+        } else {
+            $this->_headerText = __('Add URL Rewrite for a Product');
+        }
+
+        if ($this->_getProduct()->getId()) {
+            $this->_addProductLinkBlock($this->_getProduct());
+        }
+
+        if ($this->_getCategory()->getId()) {
+            $this->_addCategoryLinkBlock();
+        }
+
+        if ($this->_getProduct()->getId()) {
+            if ($this->_getCategory()->getId() || !$this->getIsCategoryMode()) {
+                $this->_addEditFormBlock();
+                $this->_updateBackButtonLink(
+                    $this->_adminhtmlData->getUrl(
+                        'adminhtml/*/edit',
+                        array('product' => $this->_getProduct()->getId())
+                    ) . 'category'
+                );
+            } else {
+                // categories selector & skip categories button
+                $this->_addCategoriesTreeBlock();
+                $this->_addSkipCategoriesBlock();
+                $this->_updateBackButtonLink($this->_adminhtmlData->getUrl('adminhtml/*/edit') . 'product');
+            }
+        } else {
+            $this->_addUrlRewriteSelectorBlock();
+            $this->_addProductsGridBlock();
+        }
+    }
+
+    /**
+     * Get or create new instance of product
+     *
+     * @return \Magento\Catalog\Model\Product
+     */
+    private function _getProduct()
+    {
+        if (!$this->hasData('product')) {
+            $this->setProduct($this->_productFactory->create());
+        }
+        return $this->getProduct();
+    }
+
+    /**
+     * Get or create new instance of category
+     *
+     * @return \Magento\Catalog\Model\Category
+     */
+    private function _getCategory()
+    {
+        if (!$this->hasData('category')) {
+            $this->setCategory($this->_categoryFactory->create());
+        }
+        return $this->getCategory();
+    }
+
+    /**
+     * Add child product link block
+     *
+     * @return void
+     */
+    private function _addProductLinkBlock()
+    {
+        $this->addChild(
+            'product_link',
+            'Magento\UrlRedirect\Block\Link',
+            array(
+                'item_url' => $this->_adminhtmlData->getUrl('adminhtml/*/*') . 'product',
+                'item_name' => $this->_getProduct()->getName(),
+                'label' => __('Product:')
+            )
+        );
+    }
+
+    /**
+     * Add child category link block
+     *
+     * @return void
+     */
+    private function _addCategoryLinkBlock()
+    {
+        $this->addChild(
+            'category_link',
+            'Magento\UrlRedirect\Block\Link',
+            array(
+                'item_url' => $this->_adminhtmlData->getUrl(
+                    'adminhtml/*/*',
+                    array('product' => $this->_getProduct()->getId())
+                ) . 'category',
+                'item_name' => $this->_getCategory()->getName(),
+                'label' => __('Category:')
+            )
+        );
+    }
+
+    /**
+     * Add child products grid block
+     *
+     * @return void
+     */
+    private function _addProductsGridBlock()
+    {
+        $this->addChild('products_grid', 'Magento\UrlRedirect\Block\Catalog\Product\Grid');
+    }
+
+    /**
+     * Add child Categories Tree block
+     *
+     * @return void
+     */
+    private function _addCategoriesTreeBlock()
+    {
+        $this->addChild('categories_tree', 'Magento\UrlRedirect\Block\Catalog\Category\Tree');
+    }
+
+    /**
+     * Add child Skip Categories block
+     *
+     * @return void
+     */
+    private function _addSkipCategoriesBlock()
+    {
+        $this->addChild(
+            'skip_categories',
+            'Magento\Backend\Block\Widget\Button',
+            array(
+                'label' => __('Skip Category Selection'),
+                'onclick' => 'window.location = \'' . $this->_adminhtmlData->getUrl(
+                    'adminhtml/*/*',
+                    array('product' => $this->_getProduct()->getId())
+                ) . '\'',
+                'class' => 'save',
+                'level' => -1
+            )
+        );
+    }
+
+    /**
+     * Creates edit form block
+     *
+     * @return \Magento\UrlRedirect\Block\Catalog\Edit\Form
+     */
+    protected function _createEditFormBlock()
+    {
+        return $this->getLayout()->createBlock(
+            'Magento\UrlRedirect\Block\Catalog\Edit\Form',
+            '',
+            array(
+                'data' => array(
+                    'product' => $this->_getProduct(),
+                    'category' => $this->_getCategory(),
+                    'url_rewrite' => $this->_getUrlRewrite()
+                )
+            )
+        );
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Block/Catalog/Product/Grid.php b/app/code/Magento/UrlRedirect/Block/Catalog/Product/Grid.php
new file mode 100644
index 0000000000000000000000000000000000000000..ae56598e355d03626d29827338b8acc21e766049
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Block/Catalog/Product/Grid.php
@@ -0,0 +1,88 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Block\Catalog\Product;
+
+/**
+ * Products grid for URL rewrites editing
+ *
+ * @author     Magento Core Team <core@magentocommerce.com>
+ */
+class Grid extends \Magento\Catalog\Block\Adminhtml\Product\Grid
+{
+    /**
+     * Disable massaction
+     *
+     * @return $this
+     */
+    protected function _prepareMassaction()
+    {
+        return $this;
+    }
+
+    /**
+     * Prepare columns layout
+     *
+     * @return $this
+     */
+    protected function _prepareColumns()
+    {
+        $this->addColumn('entity_id', array('header' => __('ID'), 'width' => 50, 'index' => 'entity_id'));
+
+        $this->addColumn('name', array('header' => __('Name'), 'index' => 'name'));
+
+        $this->addColumn('sku', array('header' => __('SKU'), 'width' => 80, 'index' => 'sku'));
+        $this->addColumn(
+            'status',
+            array(
+                'header' => __('Status'),
+                'width' => 50,
+                'index' => 'status',
+                'type' => 'options',
+                'options' => $this->_status->getOptionArray()
+            )
+        );
+        return $this;
+    }
+
+    /**
+     * Get URL for dispatching grid ajax requests
+     *
+     * @return string
+     */
+    public function getGridUrl()
+    {
+        return $this->getUrl('adminhtml/*/productGrid', array('_current' => true));
+    }
+
+    /**
+     * Return row url for js event handlers
+     *
+     * @param \Magento\Catalog\Model\Product|\Magento\Framework\Object $row
+     * @return string
+     */
+    public function getRowUrl($row)
+    {
+        return $this->getUrl('adminhtml/*/edit', array('product' => $row->getId())) . 'category';
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Block/Cms/Page/Edit.php b/app/code/Magento/UrlRedirect/Block/Cms/Page/Edit.php
new file mode 100644
index 0000000000000000000000000000000000000000..fe4960b43a92871bf9a039a1e7047ff86a6d0955
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Block/Cms/Page/Edit.php
@@ -0,0 +1,131 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Block\Cms\Page;
+
+/**
+ * Block for CMS pages URL rewrites
+ */
+class Edit extends \Magento\UrlRedirect\Block\Edit
+{
+    /**
+     * @var \Magento\Cms\Model\PageFactory
+     */
+    protected $_pageFactory;
+
+    /**
+     * @param \Magento\Backend\Block\Widget\Context $context
+     * @param \Magento\UrlRedirect\Model\UrlRedirectFactory $rewriteFactory
+     * @param \Magento\Backend\Helper\Data $adminhtmlData
+     * @param \Magento\Cms\Model\PageFactory $pageFactory
+     * @param array $data
+     */
+    public function __construct(
+        \Magento\Backend\Block\Widget\Context $context,
+        \Magento\UrlRedirect\Model\UrlRedirectFactory $rewriteFactory,
+        \Magento\Backend\Helper\Data $adminhtmlData,
+        \Magento\Cms\Model\PageFactory $pageFactory,
+        array $data = array()
+    ) {
+        $this->_pageFactory = $pageFactory;
+        parent::__construct($context, $rewriteFactory, $adminhtmlData, $data);
+    }
+
+    /**
+     * Prepare layout for URL rewrite creating for CMS page
+     *
+     * @return void
+     */
+    protected function _prepareLayoutFeatures()
+    {
+        if ($this->_getUrlRewrite()->getId()) {
+            $this->_headerText = __('Edit URL Rewrite for CMS page');
+        } else {
+            $this->_headerText = __('Add URL Rewrite for CMS page');
+        }
+
+        if ($this->_getCmsPage()->getId()) {
+            $this->_addCmsPageLinkBlock();
+            $this->_addEditFormBlock();
+            $this->_updateBackButtonLink($this->_adminhtmlData->getUrl('adminhtml/*/edit') . 'cms_page');
+        } else {
+            $this->_addUrlRewriteSelectorBlock();
+            $this->_addCmsPageGridBlock();
+        }
+    }
+
+    /**
+     * Get or create new instance of CMS page
+     *
+     * @return \Magento\Cms\Model\Page
+     */
+    private function _getCmsPage()
+    {
+        if (!$this->hasData('cms_page')) {
+            $this->setCmsPage($this->_pageFactory->create());
+        }
+        return $this->getCmsPage();
+    }
+
+    /**
+     * Add child CMS page link block
+     *
+     * @return void
+     */
+    private function _addCmsPageLinkBlock()
+    {
+        $this->addChild(
+            'cms_page_link',
+            'Magento\UrlRedirect\Block\Link',
+            array(
+                'item_url' => $this->_adminhtmlData->getUrl('adminhtml/*/*') . 'cms_page',
+                'item_name' => $this->getCmsPage()->getTitle(),
+                'label' => __('CMS page:')
+            )
+        );
+    }
+
+    /**
+     * Add child CMS page block
+     *
+     * @return void
+     */
+    private function _addCmsPageGridBlock()
+    {
+        $this->addChild('cms_pages_grid', 'Magento\UrlRedirect\Block\Cms\Page\Grid');
+    }
+
+    /**
+     * Creates edit form block
+     *
+     * @return \Magento\UrlRedirect\Block\Cms\Page\Edit\Form
+     */
+    protected function _createEditFormBlock()
+    {
+        return $this->getLayout()->createBlock(
+            'Magento\UrlRedirect\Block\Cms\Page\Edit\Form',
+            '',
+            array('data' => array('cms_page' => $this->_getCmsPage(), 'url_rewrite' => $this->_getUrlRewrite()))
+        );
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Block/Cms/Page/Edit/Form.php b/app/code/Magento/UrlRedirect/Block/Cms/Page/Edit/Form.php
new file mode 100644
index 0000000000000000000000000000000000000000..519589c91dd6b43b559de42d0450eb59d27fc0d8
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Block/Cms/Page/Edit/Form.php
@@ -0,0 +1,165 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Block\Cms\Page\Edit;
+
+/**
+ * Edit form for CMS page URL rewrites
+ *
+ * @SuppressWarnings(PHPMD.DepthOfInheritance)
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class Form extends \Magento\UrlRedirect\Block\Edit\Form
+{
+    /**
+     * @var \Magento\Cms\Model\PageFactory
+     */
+    protected $_pageFactory;
+
+    /**
+     * @var \Magento\Cms\Model\Page\UrlrewriteFactory
+     */
+    protected $_urlRewriteFactory;
+
+    /**
+     * @param \Magento\Backend\Block\Widget\Context $context
+     * @param \Magento\Framework\Registry $registry
+     * @param \Magento\Framework\Data\FormFactory $formFactory
+     * @param \Magento\UrlRedirect\Model\OptionProviderFactory $optionFactory
+     * @param \Magento\UrlRedirect\Model\UrlRedirectFactory $rewriteFactory
+     * @param \Magento\Store\Model\System\Store $systemStore
+     * @param \Magento\Backend\Helper\Data $adminhtmlData
+     * @param \Magento\Cms\Model\Page\UrlrewriteFactory $urlRewriteFactory
+     * @param \Magento\Cms\Model\PageFactory $pageFactory
+     * @param array $data
+     *
+     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
+     */
+    public function __construct(
+        \Magento\Backend\Block\Widget\Context $context,
+        \Magento\Framework\Registry $registry,
+        \Magento\Framework\Data\FormFactory $formFactory,
+        \Magento\UrlRedirect\Model\OptionProviderFactory $optionFactory,
+        \Magento\UrlRedirect\Model\UrlRedirectFactory $rewriteFactory,
+        \Magento\Store\Model\System\Store $systemStore,
+        \Magento\Backend\Helper\Data $adminhtmlData,
+        \Magento\Cms\Model\Page\UrlrewriteFactory $urlRewriteFactory,
+        \Magento\Cms\Model\PageFactory $pageFactory,
+        array $data = array()
+    ) {
+        $this->_urlRewriteFactory = $urlRewriteFactory;
+        $this->_pageFactory = $pageFactory;
+        parent::__construct(
+            $context,
+            $registry,
+            $formFactory,
+            $optionFactory,
+            $rewriteFactory,
+            $systemStore,
+            $adminhtmlData,
+            $data
+        );
+    }
+
+    /**
+     * Form post init
+     *
+     * @param \Magento\Framework\Data\Form $form
+     * @return \Magento\UrlRedirect\Block\Cms\Page\Edit\Form
+     */
+    protected function _formPostInit($form)
+    {
+        $cmsPage = $this->_getCmsPage();
+        $form->setAction(
+            $this->_adminhtmlData->getUrl(
+                'adminhtml/*/save',
+                array('id' => $this->_getModel()->getId(), 'cms_page' => $cmsPage->getId())
+            )
+        );
+
+        // Fill request path and target path elements
+        /** @var $requestPath \Magento\Framework\Data\Form\Element\AbstractElement */
+        $requestPath = $this->getForm()->getElement('request_path');
+        /** @var $targetPath \Magento\Framework\Data\Form\Element\AbstractElement */
+        $targetPath = $this->getForm()->getElement('target_path');
+
+        $model = $this->_getModel();
+        /** @var $cmsPageUrlrewrite \Magento\Cms\Model\Page\Urlrewrite */
+        $cmsPageUrlrewrite = $this->_urlRewriteFactory->create();
+        if (!$model->getId()) {
+            $sessionData = $this->_getSessionData();
+            if (!isset($sessionData['request_path'])) {
+                $requestPath->setValue($cmsPageUrlrewrite->generateRequestPath($cmsPage));
+            }
+            $targetPath->setValue($cmsPageUrlrewrite->generateTargetPath($cmsPage));
+            $disablePaths = true;
+        } else {
+            $cmsPageUrlrewrite->load($this->_getModel()->getId(), 'url_rewrite_id');
+            $disablePaths = $cmsPageUrlrewrite->getId() > 0;
+        }
+        if ($disablePaths) {
+            $targetPath->setData('disabled', true);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Get catalog entity associated stores
+     *
+     * @return array
+     * @throws \Magento\Store\Model\Exception
+     */
+    protected function _getEntityStores()
+    {
+        $cmsPage = $this->_getCmsPage();
+        $entityStores = array();
+
+        // showing websites that only associated to CMS page
+        if ($this->_getCmsPage()->getId()) {
+            $entityStores = (array)$cmsPage->getResource()->lookupStoreIds($cmsPage->getId());
+            $this->_requireStoresFilter = !in_array(0, $entityStores);
+
+            if (!$entityStores) {
+                throw new \Magento\Store\Model\Exception(
+                    __('Chosen cms page does not associated with any website.')
+                );
+            }
+        }
+
+        return $entityStores;
+    }
+
+    /**
+     * Get CMS page model instance
+     *
+     * @return \Magento\Cms\Model\Page
+     */
+    protected function _getCmsPage()
+    {
+        if (!$this->hasData('cms_page')) {
+            $this->setCmsPage($this->_pageFactory->create());
+        }
+        return $this->getCmsPage();
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Block/Cms/Page/Grid.php b/app/code/Magento/UrlRedirect/Block/Cms/Page/Grid.php
new file mode 100644
index 0000000000000000000000000000000000000000..8cb6ca507abd377a59280c5af7be0cb9117095c0
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Block/Cms/Page/Grid.php
@@ -0,0 +1,113 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Block\Cms\Page;
+
+/**
+ * CMS pages grid for URL rewrites
+ *
+ * @author     Magento Core Team <core@magentocommerce.com>
+ */
+class Grid extends \Magento\Cms\Block\Adminhtml\Page\Grid
+{
+    /**
+     * Constructor
+     *
+     * @return void
+     */
+    public function _construct()
+    {
+        parent::_construct();
+        $this->setUseAjax(true);
+    }
+
+    /**
+     * Disable massaction
+     *
+     * @return $this
+     */
+    protected function _prepareMassaction()
+    {
+        return $this;
+    }
+
+    /**
+     * Prepare columns layout
+     *
+     * @return $this
+     */
+    protected function _prepareColumns()
+    {
+        $this->addColumn('title', array('header' => __('Title'), 'align' => 'left', 'index' => 'title'));
+
+        $this->addColumn('identifier', array('header' => __('URL Key'), 'align' => 'left', 'index' => 'identifier'));
+
+        if (!$this->_storeManager->isSingleStoreMode()) {
+            $this->addColumn(
+                'store_id',
+                array(
+                    'header' => __('Store View'),
+                    'index' => 'store_id',
+                    'type' => 'store',
+                    'store_all' => true,
+                    'store_view' => true,
+                    'sortable' => false,
+                    'filter_condition_callback' => array($this, '_filterStoreCondition')
+                )
+            );
+        }
+
+        $this->addColumn(
+            'is_active',
+            array(
+                'header' => __('Status'),
+                'index' => 'is_active',
+                'type' => 'options',
+                'options' => $this->_cmsPage->getAvailableStatuses()
+            )
+        );
+
+        return $this;
+    }
+
+    /**
+     * Get URL for dispatching grid ajax requests
+     *
+     * @return string
+     */
+    public function getGridUrl()
+    {
+        return $this->getUrl('adminhtml/*/cmsPageGrid', array('_current' => true));
+    }
+
+    /**
+     * Return row url for js event handlers
+     *
+     * @param \Magento\Cms\Model\Page|\Magento\Framework\Object $row
+     * @return string
+     */
+    public function getRowUrl($row)
+    {
+        return $this->getUrl('adminhtml/*/edit', array('cms_page' => $row->getId()));
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Block/Edit.php b/app/code/Magento/UrlRedirect/Block/Edit.php
new file mode 100644
index 0000000000000000000000000000000000000000..deb100ce6ff0c3363fa5cee52f24bc56894dfc75
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Block/Edit.php
@@ -0,0 +1,298 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Block;
+
+/**
+ * Block for URL rewrites edit page
+ */
+class Edit extends \Magento\Backend\Block\Widget\Container
+{
+    /**
+     * @var \Magento\UrlRedirect\Block\Selector
+     */
+    private $_selectorBlock;
+
+    /**
+     * Part for building some blocks names
+     *
+     * @var string
+     */
+    protected $_controller = 'urlredirect';
+
+    /**
+     * Generated buttons html cache
+     *
+     * @var string
+     */
+    protected $_buttonsHtml;
+
+    /**
+     * Adminhtml data
+     *
+     * @var \Magento\Backend\Helper\Data
+     */
+    protected $_adminhtmlData = null;
+
+    /**
+     * @var \Magento\UrlRedirect\Model\UrlRedirectFactory
+     */
+    protected $_rewriteFactory;
+
+    /**
+     * @param \Magento\Backend\Block\Widget\Context $context
+     * @param \Magento\UrlRedirect\Model\UrlRedirectFactory $rewriteFactory
+     * @param \Magento\Backend\Helper\Data $adminhtmlData
+     * @param array $data
+     */
+    public function __construct(
+        \Magento\Backend\Block\Widget\Context $context,
+        \Magento\UrlRedirect\Model\UrlRedirectFactory $rewriteFactory,
+        \Magento\Backend\Helper\Data $adminhtmlData,
+        array $data = array()
+    ) {
+        $this->_rewriteFactory = $rewriteFactory;
+        $this->_adminhtmlData = $adminhtmlData;
+        parent::__construct($context, $data);
+    }
+
+    /**
+     * Prepare URL rewrite editing layout
+     *
+     * @return $this
+     */
+    protected function _prepareLayout()
+    {
+        $this->setTemplate('edit.phtml');
+
+        $this->_addBackButton();
+        $this->_prepareLayoutFeatures();
+
+        return parent::_prepareLayout();
+    }
+
+    /**
+     * Prepare featured blocks for layout of URL rewrite editing
+     *
+     * @return void
+     */
+    protected function _prepareLayoutFeatures()
+    {
+        if ($this->_getUrlRewrite()->getId()) {
+            $this->_headerText = __('Edit URL Rewrite');
+        } else {
+            $this->_headerText = __('Add New URL Rewrite');
+        }
+
+        $this->_updateBackButtonLink(
+            $this->_adminhtmlData->getUrl('adminhtml/*/edit') . $this->_getSelectorBlock()->getDefaultMode()
+        );
+        $this->_addUrlRewriteSelectorBlock();
+        $this->_addEditFormBlock();
+    }
+
+    /**
+     * Add child edit form block
+     *
+     * @return void
+     */
+    protected function _addEditFormBlock()
+    {
+        $this->setChild('form', $this->_createEditFormBlock());
+
+        if ($this->_getUrlRewrite()->getId()) {
+            $this->_addResetButton();
+            $this->_addDeleteButton();
+        }
+
+        $this->_addSaveButton();
+    }
+
+    /**
+     * Add reset button
+     *
+     * @return void
+     */
+    protected function _addResetButton()
+    {
+        $this->_addButton(
+            'reset',
+            array(
+                'label' => __('Reset'),
+                'onclick' => '$(\'edit_form\').reset()',
+                'class' => 'scalable',
+                'level' => -1
+            )
+        );
+    }
+
+    /**
+     * Add back button
+     *
+     * @return void
+     */
+    protected function _addBackButton()
+    {
+        $this->_addButton(
+            'back',
+            array(
+                'label' => __('Back'),
+                'onclick' => 'setLocation(\'' . $this->_adminhtmlData->getUrl('adminhtml/*/') . '\')',
+                'class' => 'back',
+                'level' => -1
+            )
+        );
+    }
+
+    /**
+     * Update Back button location link
+     *
+     * @param string $link
+     * @return void
+     */
+    protected function _updateBackButtonLink($link)
+    {
+        $this->_updateButton('back', 'onclick', 'setLocation(\'' . $link . '\')');
+    }
+
+    /**
+     * Add delete button
+     *
+     * @return void
+     */
+    protected function _addDeleteButton()
+    {
+        $this->_addButton(
+            'delete',
+            array(
+                'label' => __('Delete'),
+                'onclick' => 'deleteConfirm(' . json_encode(__('Are you sure you want to do this?'))
+                    . ','
+                    . json_encode(
+                        $this->_adminhtmlData->getUrl(
+                            'adminhtml/*/delete',
+                            array('id' => $this->getUrlRewrite()->getId())
+                        )
+                    )
+                    . ')',
+                'class' => 'scalable delete',
+                'level' => -1
+            )
+        );
+    }
+
+    /**
+     * Add save button
+     *
+     * @return void
+     */
+    protected function _addSaveButton()
+    {
+        $this->_addButton(
+            'save',
+            array(
+                'label' => __('Save'),
+                'class' => 'save primary save-url-redirect',
+                'level' => -1,
+                'data_attribute' => array(
+                    'mage-init' => array('button' => array('event' => 'save', 'target' => '#edit_form'))
+                )
+            )
+        );
+    }
+
+    /**
+     * Creates edit form block
+     *
+     * @return \Magento\UrlRedirect\Block\Edit\Form
+     */
+    protected function _createEditFormBlock()
+    {
+        return $this->getLayout()->createBlock(
+            'Magento\UrlRedirect\Block\Edit\Form',
+            '',
+            array('data' => array('url_rewrite' => $this->_getUrlRewrite()))
+        );
+    }
+
+    /**
+     * Add child URL rewrite selector block
+     *
+     * @return void
+     */
+    protected function _addUrlRewriteSelectorBlock()
+    {
+        $this->setChild('selector', $this->_getSelectorBlock());
+    }
+
+    /**
+     * Get selector block
+     *
+     * @return \Magento\UrlRedirect\Block\Selector
+     */
+    private function _getSelectorBlock()
+    {
+        if (!$this->_selectorBlock) {
+            $this->_selectorBlock = $this->getLayout()->createBlock('Magento\UrlRedirect\Block\Selector');
+        }
+        return $this->_selectorBlock;
+    }
+
+    /**
+     * Get container buttons HTML
+     *
+     * Since buttons are set as children, we remove them as children after generating them
+     * not to duplicate them in future
+     *
+     * @param null $area
+     * @return string
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function getButtonsHtml($area = null)
+    {
+        if (null === $this->_buttonsHtml) {
+            $this->_buttonsHtml = parent::getButtonsHtml();
+            $layout = $this->getLayout();
+            foreach ($this->getChildNames() as $name) {
+                $alias = $layout->getElementAlias($name);
+                if (false !== strpos($alias, '_button')) {
+                    $layout->unsetChild($this->getNameInLayout(), $alias);
+                }
+            }
+        }
+        return $this->_buttonsHtml;
+    }
+
+    /**
+     * Get or create new instance of URL rewrite
+     *
+     * @return \Magento\UrlRedirect\Model\UrlRedirect
+     */
+    protected function _getUrlRewrite()
+    {
+        if (!$this->hasData('url_rewrite')) {
+            $this->setUrlRewrite($this->_rewriteFactory->create());
+        }
+        return $this->getUrlRewrite();
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Block/Edit/Form.php b/app/code/Magento/UrlRedirect/Block/Edit/Form.php
new file mode 100644
index 0000000000000000000000000000000000000000..82bc37e8b82edbc168c84f8ed9a167341898a0c3
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Block/Edit/Form.php
@@ -0,0 +1,387 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Block\Edit;
+
+/**
+ * URL rewrites edit form
+ *
+ * @SuppressWarnings(PHPMD.DepthOfInheritance)
+ */
+class Form extends \Magento\Backend\Block\Widget\Form\Generic
+{
+    /**
+     * @var array
+     */
+    protected $_sessionData = null;
+
+    /**
+     * @var array
+     */
+    protected $_allStores = null;
+
+    /**
+     * @var bool
+     */
+    protected $_requireStoresFilter = false;
+
+    /**
+     * @var array
+     */
+    protected $_formValues = array();
+
+    /**
+     * Adminhtml data
+     *
+     * @var \Magento\Backend\Helper\Data
+     */
+    protected $_adminhtmlData = null;
+
+    /**
+     * @var \Magento\Store\Model\System\Store
+     */
+    protected $_systemStore;
+
+    /**
+     * @var \Magento\UrlRedirect\Model\UrlRedirectFactory
+     */
+    protected $_rewriteFactory;
+
+    /**
+     * @var \Magento\UrlRedirect\Model\OptionProviderFactory
+     */
+    protected $_optionFactory;
+
+    /**
+     * @param \Magento\Backend\Block\Widget\Context $context
+     * @param \Magento\Framework\Registry $registry
+     * @param \Magento\Framework\Data\FormFactory $formFactory
+     * @param \Magento\UrlRedirect\Model\OptionProviderFactory $optionFactory
+     * @param \Magento\UrlRedirect\Model\UrlRedirectFactory $rewriteFactory
+     * @param \Magento\Store\Model\System\Store $systemStore
+     * @param \Magento\Backend\Helper\Data $adminhtmlData
+     * @param array $data
+     */
+    public function __construct(
+        \Magento\Backend\Block\Widget\Context $context,
+        \Magento\Framework\Registry $registry,
+        \Magento\Framework\Data\FormFactory $formFactory,
+        \Magento\UrlRedirect\Model\OptionProviderFactory $optionFactory,
+        \Magento\UrlRedirect\Model\UrlRedirectFactory $rewriteFactory,
+        \Magento\Store\Model\System\Store $systemStore,
+        \Magento\Backend\Helper\Data $adminhtmlData,
+        array $data = array()
+    ) {
+        $this->_optionFactory = $optionFactory;
+        $this->_rewriteFactory = $rewriteFactory;
+        $this->_systemStore = $systemStore;
+        $this->_adminhtmlData = $adminhtmlData;
+        parent::__construct($context, $registry, $formFactory, $data);
+    }
+
+    /**
+     * Set form id and title
+     *
+     * @return void
+     */
+    protected function _construct()
+    {
+        parent::_construct();
+        $this->setId('urlrewrite_form');
+        $this->setTitle(__('Block Information'));
+    }
+
+    /**
+     * Initialize form values
+     * Set form data either from model values or from session
+     *
+     * @return $this
+     */
+    protected function _initFormValues()
+    {
+        $model = $this->_getModel();
+        $this->_formValues = array(
+            'store_id' => $model->getStoreId(),
+            'entity_type' => $model->getEntityType(),
+            'entity_id' => $model->getEntityId(),
+            'request_path' => $model->getRequestPath(),
+            'target_path' => $model->getTargetPath(),
+            'redirect_type' => $model->getRedirectType(),
+            'description' => $model->getDescription()
+        );
+
+        $sessionData = $this->_getSessionData();
+        if ($sessionData) {
+            foreach (array_keys($this->_formValues) as $key) {
+                if (isset($sessionData[$key])) {
+                    $this->_formValues[$key] = $sessionData[$key];
+                }
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Prepare the form layout
+     *
+     * @return $this
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    protected function _prepareForm()
+    {
+        $this->_initFormValues();
+
+        // Prepare form
+        /** @var \Magento\Framework\Data\Form $form */
+        $form = $this->_formFactory->create(
+            array('data' => array('id' => 'edit_form', 'use_container' => true, 'method' => 'post'))
+        );
+
+        $fieldset = $form->addFieldset('base_fieldset', array('legend' => __('URL Rewrite Information')));
+
+        $fieldset->addField(
+            'entity_type',
+            'hidden',
+            array(
+                'name' => 'entity_type',
+                'value' => $this->_formValues['entity_type']
+            )
+        );
+
+        $fieldset->addField(
+            'entity_id',
+            'hidden',
+            array(
+                'name' => 'entity_id',
+                'value' => $this->_formValues['entity_id']
+            )
+        );
+
+        $this->_prepareStoreElement($fieldset);
+
+        $fieldset->addField(
+            'request_path',
+            'text',
+            array(
+                'label' => __('Request Path'),
+                'title' => __('Request Path'),
+                'name' => 'request_path',
+                'required' => true,
+                'value' => $this->_formValues['request_path']
+            )
+        );
+
+        $fieldset->addField(
+            'target_path',
+            'text',
+            array(
+                'label' => __('Target Path'),
+                'title' => __('Target Path'),
+                'name' => 'target_path',
+                'required' => true,
+                'disabled' => false,
+                'value' => $this->_formValues['target_path']
+            )
+        );
+
+        /** @var $optionsModel \Magento\UrlRedirect\Model\OptionProvider */
+        $optionsModel = $this->_optionFactory->create();
+        $fieldset->addField(
+            'redirect_type',
+            'select',
+            array(
+                'label' => __('Redirect'),
+                'title' => __('Redirect'),
+                'name' => 'redirect_type',
+                'options' => $optionsModel->getAllOptions(),
+                'value' => $this->_formValues['redirect_type']
+            )
+        );
+
+        $fieldset->addField(
+            'description',
+            'textarea',
+            array(
+                'label' => __('Description'),
+                'title' => __('Description'),
+                'name' => 'description',
+                'cols' => 20,
+                'rows' => 5,
+                'value' => $this->_formValues['description'],
+                'wrap' => 'soft'
+            )
+        );
+
+        $this->setForm($form);
+        $this->_formPostInit($form);
+
+        return parent::_prepareForm();
+    }
+
+    /**
+     * Prepare store element
+     *
+     * @param \Magento\Framework\Data\Form\Element\Fieldset $fieldset
+     * @return void
+     */
+    protected function _prepareStoreElement($fieldset)
+    {
+        if ($this->_storeManager->isSingleStoreMode()) {
+            $fieldset->addField(
+                'store_id',
+                'hidden',
+                array('name' => 'store_id', 'value' => $this->_storeManager->getStore(true)->getId())
+            );
+        } else {
+            /** @var $renderer \Magento\Backend\Block\Store\Switcher\Form\Renderer\Fieldset\Element */
+            $renderer = $this->getLayout()->createBlock(
+                'Magento\Backend\Block\Store\Switcher\Form\Renderer\Fieldset\Element'
+            );
+
+            $storeElement = $fieldset->addField(
+                'store_id',
+                'select',
+                array(
+                    'label' => __('Store'),
+                    'title' => __('Store'),
+                    'name' => 'store_id',
+                    'required' => true,
+                    'values' => $this->_getRestrictedStoresList(),
+                    'value' => $this->_formValues['store_id']
+                )
+            );
+            $storeElement->setRenderer($renderer);
+        }
+    }
+
+    /**
+     * Form post init
+     *
+     * @param \Magento\Framework\Data\Form $form
+     * @return $this
+     */
+    protected function _formPostInit($form)
+    {
+        $form->setAction(
+            $this->_adminhtmlData->getUrl('adminhtml/*/save', array('id' => $this->_getModel()->getId()))
+        );
+        return $this;
+    }
+
+    /**
+     * Get session data
+     *
+     * @return array
+     */
+    protected function _getSessionData()
+    {
+        if (is_null($this->_sessionData)) {
+            $this->_sessionData = $this->_backendSession->getData('urlrewrite_data', true);
+        }
+        return $this->_sessionData;
+    }
+
+    /**
+     * Get URL rewrite model instance
+     *
+     * @return \Magento\UrlRedirect\Model\UrlRedirect
+     */
+    protected function _getModel()
+    {
+        if (!$this->hasData('url_rewrite')) {
+            $this->setUrlRewrite($this->_rewriteFactory->create());
+        }
+        return $this->getUrlRewrite();
+    }
+
+    /**
+     * Get request stores
+     *
+     * @return array
+     */
+    protected function _getAllStores()
+    {
+        if (is_null($this->_allStores)) {
+            $this->_allStores = $this->_systemStore->getStoreValuesForForm();
+        }
+
+        return $this->_allStores;
+    }
+
+    /**
+     * Get entity stores
+     *
+     * @return array
+     */
+    protected function _getEntityStores()
+    {
+        return $this->_getAllStores();
+    }
+
+    /**
+     * Get restricted stores list
+     * Stores should be filtered only if custom entity is specified.
+     * If we use custom rewrite, all stores are accepted.
+     *
+     * @return array
+     */
+    protected function _getRestrictedStoresList()
+    {
+        $stores = $this->_getAllStores();
+        $entityStores = $this->_getEntityStores();
+        $stores = $this->_getStoresListRestrictedByEntityStores($stores, $entityStores);
+
+        return $stores;
+    }
+
+    /**
+     * Get stores list restricted by entity stores
+     *
+     * @param array $stores
+     * @param array $entityStores
+     * @return array
+     */
+    private function _getStoresListRestrictedByEntityStores(array $stores, array $entityStores)
+    {
+        if ($this->_requireStoresFilter) {
+            foreach ($stores as $i => $store) {
+                if (isset($store['value']) && $store['value']) {
+                    $found = false;
+                    foreach ($store['value'] as $k => $v) {
+                        if (isset($v['value']) && in_array($v['value'], $entityStores)) {
+                            $found = true;
+                        } else {
+                            unset($stores[$i]['value'][$k]);
+                        }
+                    }
+                    if (!$found) {
+                        unset($stores[$i]);
+                    }
+                }
+            }
+        }
+
+        return $stores;
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Block/GridContainer.php b/app/code/Magento/UrlRedirect/Block/GridContainer.php
new file mode 100644
index 0000000000000000000000000000000000000000..b949f48d40fc37f2d05c326826ff3b26b71db009
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Block/GridContainer.php
@@ -0,0 +1,90 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Block;
+
+/**
+ * Block for Urlrewrites grid container
+ */
+class GridContainer extends \Magento\Backend\Block\Widget\Grid\Container
+{
+    /**
+     * Part for generating apropriate grid block name
+     *
+     * @var string
+     */
+    protected $_controller = 'urlredirect';
+
+    /**
+     * @var \Magento\UrlRedirect\Block\Selector
+     */
+    protected $_urlrewriteSelector;
+
+    /**
+     * @param \Magento\Backend\Block\Widget\Context $context
+     * @param Selector $urlrewriteSelector
+     * @param array $data
+     */
+    public function __construct(
+        \Magento\Backend\Block\Widget\Context $context,
+        \Magento\UrlRedirect\Block\Selector $urlrewriteSelector,
+        array $data = array()
+    ) {
+        $this->_urlrewriteSelector = $urlrewriteSelector;
+        parent::__construct($context, $data);
+    }
+
+    /**
+     * Set custom labels and headers
+     *
+     * @return void
+     */
+    protected function _construct()
+    {
+        $this->_headerText = __('URL Rewrite Management');
+        $this->_addButtonLabel = __('Add URL Rewrite');
+        parent::_construct();
+    }
+
+    /**
+     * Customize grid row URLs
+     *
+     * @return string
+     */
+    public function getCreateUrl()
+    {
+        $url = $this->getUrl('adminhtml/*/edit');
+
+        $selectorBlock = $this->getSelectorBlock();
+        if ($selectorBlock === null) {
+            $selectorBlock = $this->_urlrewriteSelector;
+        }
+
+        if ($selectorBlock) {
+            $modes = array_keys($selectorBlock->getModes());
+            $url .= reset($modes);
+        }
+
+        return $url;
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Block/Link.php b/app/code/Magento/UrlRedirect/Block/Link.php
new file mode 100644
index 0000000000000000000000000000000000000000..942f4db971a91b777973f6e9e083c04464377253
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Block/Link.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/**
+ * Label & link block
+ *
+ * @method string getLabel()
+ * @method string getItemUrl()
+ * @method string getItemName()
+ */
+namespace Magento\UrlRedirect\Block;
+
+class Link extends \Magento\Framework\View\Element\AbstractBlock
+{
+    /**
+     * Render output
+     *
+     * @return string
+     */
+    protected function _toHtml()
+    {
+        return '<p>' . $this->getLabel() . ' <a href="' . $this->getItemUrl() . '">' . $this->escapeHtml(
+            $this->getItemName()
+        ) . '</a></p>';
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Block/Selector.php b/app/code/Magento/UrlRedirect/Block/Selector.php
new file mode 100644
index 0000000000000000000000000000000000000000..643c3f84d6537183c1bb5a68a446a236f7e34c3f
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Block/Selector.php
@@ -0,0 +1,97 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Block;
+
+class Selector extends \Magento\Framework\View\Element\Template
+{
+    /**
+     * List of available modes from source model
+     * key => label
+     *
+     * @var array
+     */
+    protected $_modes;
+
+    /**
+     * @var string
+     */
+    protected $_template = 'selector.phtml';
+
+    /**
+     * Set block template and get available modes
+     *
+     * @return void
+     */
+    protected function _construct()
+    {
+        $this->_modes = array(
+            'category' => __('For category'),
+            'product' => __('For product'),
+            'cms_page' => __('For CMS page'),
+            'id' => __('Custom')
+        );
+    }
+
+    /**
+     * Available modes getter
+     *
+     * @return array
+     */
+    public function getModes()
+    {
+        return $this->_modes;
+    }
+
+    /**
+     * Label getter
+     *
+     * @return string
+     */
+    public function getSelectorLabel()
+    {
+        return __('Create URL Rewrite:');
+    }
+
+    /**
+     * Check whether selection is in specified mode
+     *
+     * @param string $mode
+     * @return bool
+     */
+    public function isMode($mode)
+    {
+        return $this->getRequest()->has($mode);
+    }
+
+    /**
+     * Get default mode
+     *
+     * @return string
+     */
+    public function getDefaultMode()
+    {
+        $keys = array_keys($this->_modes);
+        return array_shift($keys);
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Controller/Adminhtml/UrlRedirect.php b/app/code/Magento/UrlRedirect/Controller/Adminhtml/UrlRedirect.php
new file mode 100644
index 0000000000000000000000000000000000000000..d840d589a387f96ed1cc6e29c60b0e38607bf742
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Controller/Adminhtml/UrlRedirect.php
@@ -0,0 +1,468 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Controller\Adminhtml;
+
+use Magento\Backend\App\Action;
+use Magento\Catalog\Model\Category;
+use Magento\Catalog\Model\Product;
+use Magento\Framework\Model\Exception;
+
+class UrlRedirect extends Action
+{
+    /**#@+
+     * Entity types
+     */
+    const ENTITY_TYPE_CUSTOM = 'custom';
+    const ENTITY_TYPE_PRODUCT = 'product';
+    const ENTITY_TYPE_CATEGORY = 'category';
+    const ENTITY_TYPE_CMS_PAGE = 'cms-page';
+    /**#@-*/
+
+    const ID_MODE = 'id';
+
+    const PRODUCT_MODE = 'product';
+
+    const CATEGORY_MODE = 'category';
+
+    const CMS_PAGE_MODE = 'cms_page';
+
+    /**
+     * @var Product
+     */
+    private $_product;
+
+    /**
+     * @var Category
+     */
+    private $_category;
+
+    /**
+     * @var \Magento\Cms\Model\Page
+     */
+    private $_cmsPage;
+
+    /**
+     * @var \Magento\UrlRedirect\Model\UrlRedirect
+     */
+    private $_urlRewrite;
+
+    /**
+     * Show URL rewrites index page
+     *
+     * @return void
+     */
+    public function indexAction()
+    {
+        $this->_title->add(__('URL Rewrites'));
+
+        $this->_view->loadLayout();
+        $this->_setActiveMenu('Magento_UrlRedirect::urlrewrite');
+        $this->_view->renderLayout();
+    }
+
+    /**
+     * Show urlrewrite edit/create page
+     *
+     * @return void
+     */
+    public function editAction()
+    {
+        $this->_title->add(__('URL Rewrites'));
+        $this->_title->add(__('[New/Edit] URL Rewrite'));
+
+        $this->_view->loadLayout();
+        $this->_setActiveMenu('Magento_UrlRedirect::urlrewrite');
+
+        $mode = $this->_getMode();
+        switch ($mode) {
+            case self::PRODUCT_MODE:
+                $editBlock = $this->_view->getLayout()->createBlock(
+                    'Magento\UrlRedirect\Block\Catalog\Product\Edit',
+                    '',
+                    array(
+                        'data' => array(
+                            'category' => $this->_getCategory(),
+                            'product' => $this->_getProduct(),
+                            'is_category_mode' => $this->getRequest()->has('category'),
+                            'url_rewrite' => $this->_getUrlRewrite()
+                        )
+                    )
+                );
+                break;
+            case self::CATEGORY_MODE:
+                $editBlock = $this->_view->getLayout()->createBlock(
+                    'Magento\UrlRedirect\Block\Catalog\Category\Edit',
+                    '',
+                    array(
+                        'data' => array('category' => $this->_getCategory(), 'url_rewrite' => $this->_getUrlRewrite())
+                    )
+                );
+                break;
+            case self::CMS_PAGE_MODE:
+                $editBlock = $this->_view->getLayout()->createBlock(
+                    'Magento\UrlRedirect\Block\Cms\Page\Edit',
+                    '',
+                    array(
+                        'data' => array('cms_page' => $this->_getCmsPage(), 'url_rewrite' => $this->_getUrlRewrite())
+                    )
+                );
+                break;
+            case self::ID_MODE:
+            default:
+                $editBlock = $this->_view->getLayout()->createBlock(
+                    'Magento\UrlRedirect\Block\Edit',
+                    '',
+                    array('data' => array('url_rewrite' => $this->_getUrlRewrite()))
+                );
+                break;
+        }
+
+        $this->_addContent($editBlock);
+        if (in_array($mode, array(self::PRODUCT_MODE, self::CATEGORY_MODE))) {
+            $this->_view->getLayout()->getBlock('head')->setCanLoadExtJs(true);
+        }
+        $this->_view->renderLayout();
+    }
+
+    /**
+     * Get current mode
+     *
+     * @return string
+     */
+    private function _getMode()
+    {
+        if ($this->_getProduct()->getId() || $this->getRequest()->has('product')) {
+            $mode = self::PRODUCT_MODE;
+        } elseif ($this->_getCategory()->getId() || $this->getRequest()->has('category')) {
+            $mode = self::CATEGORY_MODE;
+        } elseif ($this->_getCmsPage()->getId() || $this->getRequest()->has('cms_page')) {
+            $mode = self::CMS_PAGE_MODE;
+        } elseif ($this->getRequest()->has('id')) {
+            $mode = self::ID_MODE;
+        } else {
+            $mode = $this->_objectManager->get('Magento\UrlRedirect\Block\Selector')->getDefaultMode();
+        }
+        return $mode;
+    }
+
+    /**
+     * Ajax products grid action
+     *
+     * @return void
+     */
+    public function productGridAction()
+    {
+        $this->getResponse()->setBody(
+            $this->_view->getLayout()->createBlock('Magento\UrlRedirect\Block\Catalog\Product\Grid')->toHtml()
+        );
+    }
+
+    /**
+     * Ajax categories tree loader action
+     *
+     * @return void
+     */
+    public function categoriesJsonAction()
+    {
+        $categoryId = $this->getRequest()->getParam('id', null);
+        $this->getResponse()->setBody(
+            $this->_objectManager->get(
+                'Magento\UrlRedirect\Block\Catalog\Category\Tree'
+            )->getTreeArray(
+                $categoryId,
+                true,
+                1
+            )
+        );
+    }
+
+    /**
+     * Ajax CMS pages grid action
+     *
+     * @return void
+     */
+    public function cmsPageGridAction()
+    {
+        $this->getResponse()->setBody(
+            $this->_view->getLayout()->createBlock('Magento\UrlRedirect\Block\Cms\Page\Grid')->toHtml()
+        );
+    }
+
+    /**
+     * Urlrewrite save action
+     *
+     * @return void
+     */
+    public function saveAction()
+    {
+        if ($data = $this->getRequest()->getPost()) {
+            /** @var $session \Magento\Backend\Model\Session */
+            $session = $this->_objectManager->get('Magento\Backend\Model\Session');
+            try {
+                /** @var $model \Magento\UrlRedirect\Model\UrlRedirect */
+                $model = $this->_getUrlRewrite();
+
+                $requestPath = $this->getRequest()->getParam('request_path');
+                $this->_objectManager->get('Magento\UrlRedirect\Helper\UrlRewrite')->validateRequestPath($requestPath);
+
+                $model->setEntityType($this->getRequest()->getParam('entity_type', self::ENTITY_TYPE_CUSTOM))
+                    ->setStoreId($this->getRequest()->getParam('store_id', 0))
+                    ->setTargetPath($this->getRequest()->getParam('target_path'))
+                    ->setRedirectType($this->getRequest()->getParam('redirect_type'))
+                    ->setDescription($this->getRequest()->getParam('description'))
+                    ->setRequestPath($requestPath);
+
+                $this->_onUrlRewriteSaveBefore($model);
+
+                $model->save();
+
+                $this->messageManager->addSuccess(__('The URL Rewrite has been saved.'));
+                $this->_redirect('adminhtml/*/');
+                return;
+            } catch (Exception $e) {
+                $this->messageManager->addError($e->getMessage());
+                $session->setUrlrewriteData($data);
+            } catch (\Exception $e) {
+                $this->messageManager->addException($e, __('An error occurred while saving URL Rewrite.'));
+                $session->setUrlrewriteData($data);
+            }
+        }
+        $this->getResponse()->setRedirect($this->_redirect->getRedirectUrl($this->getUrl('*')));
+    }
+
+    /**
+     * Call before save urlrewrite handlers
+     *
+     * @param \Magento\UrlRedirect\Model\UrlRedirect $model
+     * @return void
+     */
+    protected function _onUrlRewriteSaveBefore($model)
+    {
+        $this->_handleCatalogUrlRewrite($model);
+        $this->_handleCmsPageUrlRewrite($model);
+    }
+
+    /**
+     * Override urlrewrite data, basing on current category and product
+     *
+     * @param \Magento\UrlRedirect\Model\UrlRedirect $model
+     * @return void
+     * @throws Exception
+     */
+    protected function _handleCatalogUrlRewrite($model)
+    {
+        $product = $this->_getInitializedProduct($model);
+        $category = $this->_getInitializedCategory($model);
+
+        if ($product || $category) {
+            /** @var $catalogUrlModel \Magento\Catalog\Model\Url */
+            $catalogUrlModel = $this->_objectManager->get('Magento\Catalog\Model\Url');
+            $model->setTargetPath($catalogUrlModel->generatePath('target', $product, $category));
+            $model->setEntityType(
+                $product && $product->getId() ? self::ENTITY_TYPE_PRODUCT : self::ENTITY_TYPE_CATEGORY
+            );
+            $model->setEntityId($product && $product->getId() ? $product->getId() : $category->getId());
+        }
+    }
+
+    /**
+     * Get product instance applicable for generatePath
+     *
+     * @param \Magento\UrlRedirect\Model\UrlRedirect $model
+     * @return Product|null
+     */
+    private function _getInitializedProduct($model)
+    {
+        /** @var $product Product */
+        $product = $this->_getProduct();
+        if ($product->getId()) {
+            $model->setProductId($product->getId());
+        } else {
+            $product = null;
+        }
+
+        return $product;
+    }
+
+    /**
+     * Get category instance applicable for generatePath
+     *
+     * @param \Magento\UrlRedirect\Model\UrlRedirect $model
+     * @return Category|null
+     */
+    private function _getInitializedCategory($model)
+    {
+        /** @var $category Category */
+        $category = $this->_getCategory();
+        if ($category->getId()) {
+            $model->setCategoryId($category->getId());
+        } else {
+            $category = null;
+        }
+        return $category;
+    }
+
+    /**
+     * Override URL rewrite data, basing on current CMS page
+     *
+     * @param \Magento\UrlRedirect\Model\UrlRedirect $model
+     * @return void
+     * @throws \Magento\Framework\Model\Exception
+     */
+    private function _handleCmsPageUrlRewrite($model)
+    {
+        /** @var $cmsPage \Magento\Cms\Model\Page */
+        $cmsPage = $this->_getCmsPage();
+        if (!$cmsPage->getId()) {
+            return;
+        }
+
+        /** @var $cmsPageUrlRewrite \Magento\Cms\Model\Page\Urlrewrite */
+        $cmsPageUrlRewrite = $this->_objectManager->create('Magento\Cms\Model\Page\Urlrewrite');
+
+        $model->setTargetPath($cmsPageUrlRewrite->generateTargetPath($cmsPage));
+        $model->setEntityType(self::ENTITY_TYPE_CMS_PAGE);
+        $model->setEntityId($cmsPage->getId());
+    }
+
+    /**
+     * URL rewrite delete action
+     *
+     * @return void
+     */
+    public function deleteAction()
+    {
+        if ($this->_getUrlRewrite()->getId()) {
+            try {
+                $this->_getUrlRewrite()->delete();
+                $this->messageManager->addSuccess(__('The URL Rewrite has been deleted.'));
+            } catch (\Exception $e) {
+                $this->messageManager->addException($e, __('An error occurred while deleting URL Rewrite.'));
+                $this->_redirect('adminhtml/*/edit/', array('id' => $this->_getUrlRewrite()->getId()));
+                return;
+            }
+        }
+        $this->_redirect('adminhtml/*/');
+    }
+
+    /**
+     * Check whether this contoller is allowed in admin permissions
+     *
+     * @return bool
+     */
+    protected function _isAllowed()
+    {
+        return $this->_authorization->isAllowed('Magento_UrlRedirect::urlrewrite');
+    }
+
+    /**
+     * Get Category from request
+     *
+     * @return Category
+     */
+    private function _getCategory()
+    {
+        if (!$this->_category) {
+            $this->_category = $this->_objectManager->create('Magento\Catalog\Model\Category');
+            $categoryId = (int)$this->getRequest()->getParam('category', 0);
+
+            if (!$categoryId && $this->_getUrlRewrite()->getId()
+                && $this->_getUrlRewrite()->getEntityType() === self::ENTITY_TYPE_CATEGORY
+            ) {
+                $categoryId = $this->_getUrlRewrite()->getEntityId();
+            }
+
+            if ($categoryId) {
+                $this->_category->load($categoryId);
+            }
+        }
+        return $this->_category;
+    }
+
+    /**
+     * Get Product from request
+     *
+     * @return Product
+     */
+    private function _getProduct()
+    {
+        if (!$this->_product) {
+            $this->_product = $this->_objectManager->create('Magento\Catalog\Model\Product');
+            $productId = (int)$this->getRequest()->getParam('product', 0);
+
+            if (!$productId && $this->_getUrlRewrite()->getId()
+                && $this->_getUrlRewrite()->getEntityType() === self::ENTITY_TYPE_PRODUCT
+            ) {
+                $productId = $this->_getUrlRewrite()->getEntityId();
+            }
+
+            if ($productId) {
+                $this->_product->load($productId);
+            }
+        }
+        return $this->_product;
+    }
+
+    /**
+     * Get CMS page from request
+     *
+     * @return \Magento\Cms\Model\Page
+     */
+    private function _getCmsPage()
+    {
+        if (!$this->_cmsPage) {
+            $this->_cmsPage = $this->_objectManager->create('Magento\Cms\Model\Page');
+            $cmsPageId = (int)$this->getRequest()->getParam('cms_page', 0);
+
+            if (!$cmsPageId && $this->_getUrlRewrite()->getId()
+                && $this->_getUrlRewrite()->getEntityType() === self::ENTITY_TYPE_CMS_PAGE
+            ) {
+                $cmsPageId = $this->_getUrlRewrite()->getEntityId();
+            }
+
+            if ($cmsPageId) {
+                $this->_cmsPage->load($cmsPageId);
+            }
+        }
+        return $this->_cmsPage;
+    }
+
+    /**
+     * Get URL rewrite from request
+     *
+     * @return \Magento\UrlRedirect\Model\UrlRedirect
+     */
+    private function _getUrlRewrite()
+    {
+        if (!$this->_urlRewrite) {
+            $this->_urlRewrite = $this->_objectManager->create('Magento\UrlRedirect\Model\UrlRedirect');
+
+            $urlRewriteId = (int)$this->getRequest()->getParam('id', 0);
+            if ($urlRewriteId) {
+                $this->_urlRewrite->load((int)$this->getRequest()->getParam('id', 0));
+            }
+        }
+        return $this->_urlRewrite;
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Controller/Router.php b/app/code/Magento/UrlRedirect/Controller/Router.php
new file mode 100644
index 0000000000000000000000000000000000000000..916578caa61510d493df9f7d282f2162a7dcd897
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Controller/Router.php
@@ -0,0 +1,106 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Controller;
+
+/**
+ * UrlRedirect Controller Router
+ */
+class Router implements \Magento\Framework\App\RouterInterface
+{
+    /** @var \Magento\Framework\UrlInterface */
+    protected $url;
+
+    /** @var \Magento\Framework\App\State */
+    protected $appState;
+
+    /** @var \Magento\Store\Model\StoreManagerInterface */
+    protected $storeManager;
+
+    /** @var \Magento\Framework\App\ResponseInterface */
+    protected $response;
+
+    /** @var \Magento\UrlRedirect\Service\V1\UrlMatcherInterface */
+    protected $urlMatcher;
+
+    /**
+     * @param \Magento\Framework\App\ActionFactory $actionFactory
+     * @param \Magento\Framework\UrlInterface $url
+     * @param \Magento\Framework\App\State $appState
+     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
+     * @param \Magento\Framework\App\ResponseInterface $response
+     * @param \Magento\UrlRedirect\Service\V1\UrlMatcherInterface $urlMatcher
+     */
+    public function __construct(
+        \Magento\Framework\App\ActionFactory $actionFactory,
+        \Magento\Framework\UrlInterface $url,
+        \Magento\Framework\App\State $appState,
+        \Magento\Store\Model\StoreManagerInterface $storeManager,
+        \Magento\Framework\App\ResponseInterface $response,
+        \Magento\UrlRedirect\Service\V1\UrlMatcherInterface $urlMatcher
+    ) {
+        parent::__construct($actionFactory);
+        $this->url = $url;
+        $this->appState = $appState;
+        $this->storeManager = $storeManager;
+        $this->response = $response;
+        $this->urlMatcher = $urlMatcher;
+    }
+
+    /**
+     * Validate and Match Cms Page and modify request
+     *
+     * @param \Magento\Framework\App\RequestInterface $request
+     * @return mixed
+     */
+    public function match(\Magento\Framework\App\RequestInterface $request)
+    {
+        if (!$this->appState->isInstalled()) {
+            $this->response->setRedirect($this->url->getUrl('install'))->sendResponse();
+            return null;
+        }
+
+        $identifier = trim($request->getPathInfo(), '/');
+        $urlRewrite = $this->urlMatcher->match($identifier, $this->storeManager->getStore()->getId());
+        if ($urlRewrite === null) {
+            return null;
+        }
+
+        $redirectType = $urlRewrite->getRedirectType();
+        if ($redirectType) {
+            $redirectCode = $redirectType == \Magento\UrlRedirect\Model\OptionProvider::PERMANENT ? 301 : 302;
+            $this->response->setRedirect($urlRewrite->getTargetPath(), $redirectCode);
+            $request->setDispatched(true);
+            return $this->_actionFactory->createController(
+                'Magento\Framework\App\Action\Redirect',
+                array('request' => $request)
+            );
+        }
+
+        $request->setPathInfo('/' . $urlRewrite->getTargetPath());
+        return $this->_actionFactory->createController(
+            'Magento\Framework\App\Action\Forward',
+            array('request' => $request)
+        );
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Helper/UrlRewrite.php b/app/code/Magento/UrlRedirect/Helper/UrlRewrite.php
new file mode 100644
index 0000000000000000000000000000000000000000..806219890e7a515e19b2a083458770675d412736
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Helper/UrlRewrite.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Helper;
+
+class UrlRewrite extends \Magento\Framework\App\Helper\AbstractHelper
+{
+    /**
+     * Validation error constants
+     */
+    const VERR_MANYSLASHES = 1;
+
+    // Too many slashes in a row of request path, e.g. '///foo//'
+    const VERR_ANCHOR = 2;
+
+    // Anchor is not supported in request path, e.g. 'foo#bar'
+
+    /**
+     * @var \Magento\UrlRedirect\Model\OptionProvider
+     */
+    protected $_urlrewrite;
+
+    /**
+     * @param \Magento\Framework\App\Helper\Context $context
+     * @param \Magento\UrlRedirect\Model\OptionProvider $urlrewrite
+     */
+    public function __construct(
+        \Magento\Framework\App\Helper\Context $context,
+        \Magento\UrlRedirect\Model\OptionProvider $urlrewrite
+    ) {
+        parent::__construct($context);
+        $this->_urlrewrite = $urlrewrite;
+    }
+
+    /**
+     * Core func to validate request path
+     * If something is wrong with a path it throws localized error message and error code,
+     * that can be checked to by wrapper func to alternate error message
+     *
+     * @param string $requestPath
+     * @return bool
+     * @throws \Exception
+     */
+    protected function _validateRequestPath($requestPath)
+    {
+        if (strpos($requestPath, '//') !== false) {
+            throw new \Exception(
+                __('Two and more slashes together are not permitted in request path'),
+                self::VERR_MANYSLASHES
+            );
+        }
+        if (strpos($requestPath, '#') !== false) {
+            throw new \Exception(__('Anchor symbol (#) is not supported in request path'), self::VERR_ANCHOR);
+        }
+        return true;
+    }
+
+    /**
+     * Validates request path
+     * Either returns TRUE (success) or throws error (validation failed)
+     *
+     * @param string $requestPath
+     * @throws \Magento\Framework\Model\Exception
+     * @return bool
+     */
+    public function validateRequestPath($requestPath)
+    {
+        try {
+            $this->_validateRequestPath($requestPath);
+        } catch (\Exception $e) {
+            throw new \Magento\Framework\Model\Exception($e->getMessage());
+        }
+        return true;
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Model/OptionProvider.php b/app/code/Magento/UrlRedirect/Model/OptionProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..46d9a7357eba72ad31cf656dbc92d468dc487835
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Model/OptionProvider.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * URL Rewrite Option Provider
+ *
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Model;
+
+use Magento\Framework\Option\ArrayInterface;
+
+class OptionProvider implements ArrayInterface
+{
+    const TEMPORARY = 'R';
+
+    const PERMANENT = 'RP';
+
+    /**
+     * @var array|null
+     */
+    protected $_options = null;
+
+    /**
+     * Get all options
+     *
+     * @return array
+     */
+    public function getAllOptions()
+    {
+        if (is_null($this->_options)) {
+            $this->_options = array(
+                '' => __('No'),
+                self::TEMPORARY => __('Temporary (302)'),
+                self::PERMANENT => __('Permanent (301)'),
+            );
+        }
+        return $this->_options;
+    }
+
+    /**
+     * Get options list (redirects only)
+     *
+     * @return string[]
+     */
+    public function getRedirectOptions()
+    {
+        return array(self::TEMPORARY, self::PERMANENT);
+    }
+
+    /**
+     * Return option array
+     *
+     * @return array
+     */
+    public function toOptionArray()
+    {
+        return $this->getAllOptions();
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Model/Resource/UrlRedirect.php b/app/code/Magento/UrlRedirect/Model/Resource/UrlRedirect.php
new file mode 100644
index 0000000000000000000000000000000000000000..f19d49ef955765e2f587cfdc0f8ad6598c7e3e22
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Model/Resource/UrlRedirect.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * URL rewrite resource model
+ *
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Model\Resource;
+
+class UrlRedirect extends \Magento\Framework\Model\Resource\Db\AbstractDb
+{
+    /**
+     * Define main table
+     *
+     * @return void
+     */
+    protected function _construct()
+    {
+        $this->_init('url_rewrite', 'url_rewrite_id');
+    }
+
+    /**
+     * Initialize array fields
+     *
+     * @return $this
+     */
+    protected function _initUniqueFields()
+    {
+        $this->_uniqueFields = array(
+            array('field' => array('request_path', 'store_id'), 'title' => __('Request Path for Specified Store'))
+        );
+        return $this;
+    }
+
+    /**
+     * Retrieve select object for load object data
+     *
+     * @param string $field
+     * @param mixed $value
+     * @param \Magento\UrlRedirect\Model\UrlRedirect $object
+     * @return \Zend_Db_Select
+     */
+    protected function _getLoadSelect($field, $value, $object)
+    {
+        /** @var $select \Magento\Framework\DB\Select */
+        $select = parent::_getLoadSelect($field, $value, $object);
+
+        if (!is_null($object->getStoreId())) {
+            $select->where(
+                'store_id IN(?)',
+                array(\Magento\Store\Model\Store::DEFAULT_STORE_ID, $object->getStoreId())
+            );
+            $select->order('store_id ' . \Magento\Framework\DB\Select::SQL_DESC);
+            $select->limit(1);
+        }
+
+        return $select;
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Model/Resource/UrlRedirect/Collection.php b/app/code/Magento/UrlRedirect/Model/Resource/UrlRedirect/Collection.php
new file mode 100644
index 0000000000000000000000000000000000000000..9cc9f17e6f3b6cb4948cf94043bce37f75795055
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Model/Resource/UrlRedirect/Collection.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * URL rewrite collection
+ *
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Model\Resource\UrlRedirect;
+
+class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
+{
+    /**
+     * Store Manager Model
+     *
+     * @var \Magento\Store\Model\StoreManagerInterface
+     */
+    protected $_storeManager;
+
+    /**
+     * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory
+     * @param \Magento\Framework\Logger $logger
+     * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
+     * @param \Magento\Framework\Event\ManagerInterface $eventManager
+     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
+     * @param mixed $connection
+     * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource
+     */
+    public function __construct(
+        \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
+        \Magento\Framework\Logger $logger,
+        \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
+        \Magento\Framework\Event\ManagerInterface $eventManager,
+        \Magento\Store\Model\StoreManagerInterface $storeManager,
+        $connection = null,
+        \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null
+    ) {
+        parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
+        $this->_storeManager = $storeManager;
+    }
+
+    /**
+     * Define resource model
+     *
+     * @return void
+     */
+    protected function _construct()
+    {
+        $this->_init('Magento\UrlRedirect\Model\UrlRedirect', 'Magento\UrlRedirect\Model\Resource\UrlRedirect');
+    }
+
+    /**
+     * Filter collections by stores
+     *
+     * @param mixed $store
+     * @param bool $withAdmin
+     * @return $this
+     */
+    public function addStoreFilter($store, $withAdmin = true)
+    {
+        if (!is_array($store)) {
+            $store = array($this->_storeManager->getStore($store)->getId());
+        }
+        if ($withAdmin) {
+            $store[] = 0;
+        }
+
+        $this->addFieldToFilter('store_id', array('in' => $store));
+
+        return $this;
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Model/Storage/AbstractStorage.php b/app/code/Magento/UrlRedirect/Model/Storage/AbstractStorage.php
new file mode 100644
index 0000000000000000000000000000000000000000..6d8dca8b501b9c5f82cf121ddb7e00f990361ea0
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Model/Storage/AbstractStorage.php
@@ -0,0 +1,119 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Model\Storage;
+
+use Magento\Framework\App\Resource;
+use Magento\UrlRedirect\Model\StorageInterface;
+use Magento\UrlRedirect\Service\V1\Data\Converter;
+use Magento\UrlRedirect\Service\V1\Data\Filter;
+
+/**
+ * Abstract db storage
+ */
+abstract class AbstractStorage implements StorageInterface
+{
+    /**
+     * @var Converter
+     */
+    protected $converter;
+
+    /**
+     * @param Converter $converter
+     */
+    public function __construct(Converter $converter)
+    {
+        $this->converter = $converter;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function findAllByFilter(Filter $filter)
+    {
+        $rows = $this->doFindAllByFilter($filter);
+
+        $urlRewrites = [];
+        foreach ($rows as $row) {
+            $urlRewrites[] = $this->createUrlRewrite($row);
+        }
+        return $urlRewrites;
+    }
+
+    /**
+     * Find all rows by specific filter. Template method
+     *
+     * @param Filter $filter
+     * @return array
+     */
+    abstract protected function doFindAllByFilter($filter);
+
+    /**
+     * {@inheritdoc}
+     */
+    public function findByFilter(Filter $filter)
+    {
+        $row = $this->doFindByFilter($filter);
+
+        return $row ? $this->createUrlRewrite($row) : null;
+    }
+
+    /**
+     * Find row by specific filter. Template method
+     *
+     * @param Filter $filter
+     * @return array
+     */
+    abstract protected function doFindByFilter($filter);
+
+    /**
+     * {@inheritdoc}
+     */
+    public function addMultiple(array $urls)
+    {
+        $flatData = [];
+        foreach ($urls as $url) {
+            $flatData[] = $this->converter->convertObjectToArray($url);
+        }
+        $this->doAddMultiple($flatData);
+    }
+
+    /**
+     * Add multiple data to storage. Template method
+     *
+     * @param array $data
+     * @return int
+     */
+    abstract protected function doAddMultiple($data);
+
+    /**
+     * Create url rewrite object
+     *
+     * @param array $data
+     * @return \Magento\UrlRedirect\Service\V1\Data\UrlRewrite
+     */
+    protected function createUrlRewrite($data)
+    {
+        return $this->converter->convertArrayToObject($data);
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Model/Storage/Db.php b/app/code/Magento/UrlRedirect/Model/Storage/Db.php
new file mode 100644
index 0000000000000000000000000000000000000000..0a477302d77afd2774a5ffc11494fb512a76e806
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Model/Storage/Db.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Model\Storage;
+
+use Magento\Framework\App\Resource;
+use Magento\UrlRedirect\Service\V1\Data\Converter;
+use Magento\UrlRedirect\Service\V1\Data\Filter;
+
+/**
+ * Db storage
+ */
+class Db extends AbstractStorage
+{
+    /**
+     * DB Storage table name
+     */
+    const TABLE_NAME = 'url_rewrite';
+
+    /**
+     * @var \Magento\Framework\DB\Adapter\AdapterInterface
+     */
+    protected $connection;
+
+    /**
+     * @param Converter $converter
+     * @param Resource $resource
+     */
+    public function __construct(Converter $converter, Resource $resource)
+    {
+        $this->connection = $resource->getConnection(Resource::DEFAULT_WRITE_RESOURCE);
+
+        parent::__construct($converter);
+    }
+
+    /**
+     * Prepare select statement for specific filter
+     *
+     * @param Filter $filter
+     * @return \Magento\Framework\DB\Select
+     */
+    protected function prepareSelect($filter)
+    {
+        $select = $this->connection->select();
+        $select->from(self::TABLE_NAME);
+
+        foreach ($filter->getFilter() as $column => $value) {
+            $select->where($this->connection->quoteIdentifier($column) . ' IN (?)', $value);
+        }
+        return $select;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function doFindAllByFilter($filter)
+    {
+        return $this->connection->fetchAll($this->prepareSelect($filter));
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function doFindByFilter($filter)
+    {
+        return $this->connection->fetchRow($this->prepareSelect($filter));
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function doAddMultiple($data)
+    {
+        $this->connection->insertMultiple(self::TABLE_NAME, $data);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function deleteByFilter(Filter $filter)
+    {
+        $this->connection->query($this->prepareSelect($filter)->deleteFromSelect(self::TABLE_NAME));
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Model/StorageInterface.php b/app/code/Magento/UrlRedirect/Model/StorageInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..c362c56460ca8c0a25e65d3da2445b9906f5906d
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Model/StorageInterface.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Model;
+
+use Magento\UrlRedirect\Service\V1\Data\Filter;
+
+/**
+ * Url Storage Interface
+ */
+interface StorageInterface
+{
+    /**
+     * Find all rows by specific filter
+     *
+     * @param Filter $filter
+     * @return \Magento\UrlRedirect\Service\V1\Data\UrlRewrite[]
+     */
+    public function findAllByFilter(Filter $filter);
+
+    /**
+     * Find row by specific filter
+     *
+     * @param Filter $filter
+     * @return \Magento\UrlRedirect\Service\V1\Data\UrlRewrite
+     */
+    public function findByFilter(Filter $filter);
+
+    /**
+     * Add multiple urls to storage
+     *
+     * @param array $urls
+     * @return void
+     */
+    public function addMultiple(array $urls);
+
+    /**
+     * Delete data from storage by specific filter
+     *
+     * @param Filter $filter
+     * @return void
+     */
+    public function deleteByFilter(Filter $filter);
+}
diff --git a/app/code/Magento/UrlRedirect/Model/UrlRedirect.php b/app/code/Magento/UrlRedirect/Model/UrlRedirect.php
new file mode 100644
index 0000000000000000000000000000000000000000..4935d63bc805f2b18d69cd2f60310a50ca621674
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Model/UrlRedirect.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * URL Rewrite Model
+ *
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Model;
+
+/**
+ * @method string getEntityType()
+ * @method UrlRedirect setEntityType(string $value)
+ * @method int getEntityId()
+ * @method UrlRedirect setEntityId(int $value)
+ */
+class UrlRedirect extends \Magento\Framework\Model\AbstractModel
+{
+    /**
+     * Initialize corresponding resource model
+     *
+     * @return void
+     */
+    protected function _construct()
+    {
+        $this->_init('Magento\UrlRedirect\Model\Resource\UrlRedirect');
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Service/V1/Data/Converter.php b/app/code/Magento/UrlRedirect/Service/V1/Data/Converter.php
new file mode 100644
index 0000000000000000000000000000000000000000..a7847b0d84b4bd5b77855e77414d76ce9f0956ac
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Service/V1/Data/Converter.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Service\V1\Data;
+
+use Magento\Framework\Service\DataObjectConverter;
+use Magento\UrlRedirect\Service\V1\Data\UrlRewriteBuilderFactory;
+
+/**
+ * Data object converter
+ */
+class Converter
+{
+    /**
+     * @var UrlRewriteBuilderFactory
+     */
+    protected $builderFactory;
+
+    /**
+     * @param UrlRewriteBuilderFactory $builderFactory
+     */
+    public function __construct(UrlRewriteBuilderFactory $builderFactory)
+    {
+        $this->builderFactory = $builderFactory;
+    }
+
+    /**
+     * Convert array to Service Data Object
+     *
+     * @param array $data
+     * @return UrlRewrite
+     */
+    public function convertArrayToObject(array $data)
+    {
+        return $this->builderFactory->create()->populateWithArray($data)->create();
+    }
+
+    /**
+     * Convert Service Data Object to array
+     *
+     * @param UrlRewrite $object
+     * @return array
+     */
+    public function convertObjectToArray(UrlRewrite $object)
+    {
+        return DataObjectConverter::toFlatArray($object);
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Service/V1/Data/Filter.php b/app/code/Magento/UrlRedirect/Service/V1/Data/Filter.php
new file mode 100644
index 0000000000000000000000000000000000000000..f2fc91a18a336d255e0514ed90c87760b0c1e7ea
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Service/V1/Data/Filter.php
@@ -0,0 +1,138 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Service\V1\Data;
+
+/**
+ * Url rewrite search filter
+ */
+class Filter
+{
+    /**
+     * Data with filter values
+     *
+     * @var array
+     */
+    protected $data = [];
+
+    /**
+     * Possible fields for filter
+     *
+     * @var array
+     */
+    protected $possibleFields = [
+        UrlRewrite::ENTITY_ID,
+        UrlRewrite::ENTITY_TYPE,
+        UrlRewrite::STORE_ID,
+        UrlRewrite::REQUEST_PATH,
+        UrlRewrite::REDIRECT_TYPE,
+    ];
+
+    /**
+     * Filter constructor
+     *
+     * @param array $filterData
+     * @throws \InvalidArgumentException
+     */
+    public function __construct(array $filterData = [])
+    {
+        if ($filterData) {
+            if ($wrongFields = array_diff(array_keys($filterData), $this->possibleFields)) {
+                throw new \InvalidArgumentException(
+                    sprintf('There is wrong fields passed to filter: "%s"', implode(', ', $wrongFields))
+                );
+            }
+            $this->data = $filterData;
+        }
+        return $this;
+    }
+
+    /**
+     * @param string $key
+     * @param mixed $value
+     * @return $this
+     */
+    protected function _set($key, $value)
+    {
+        $this->data[$key] = $value;
+        return $this;
+    }
+
+    /**
+     * @return array
+     */
+    public function getFilter()
+    {
+        return $this->data;
+    }
+
+    /**
+     * @param int $entityId
+     *
+     * @return $this
+     */
+    public function setEntityId($entityId)
+    {
+        return $this->_set(UrlRewrite::ENTITY_ID, $entityId);
+    }
+
+    /**
+     * @param int|array $entityType
+     *
+     * @return $this
+     */
+    public function setEntityType($entityType)
+    {
+        return $this->_set(UrlRewrite::ENTITY_TYPE, $entityType);
+    }
+
+    /**
+     * @param string $requestPath
+     *
+     * @return $this
+     */
+    public function setRequestPath($requestPath)
+    {
+        return $this->_set(UrlRewrite::REQUEST_PATH, $requestPath);
+    }
+
+    /**
+     * @param int $storeId
+     *
+     * @return $this
+     */
+    public function setStoreId($storeId)
+    {
+        return $this->_set(UrlRewrite::STORE_ID, $storeId);
+    }
+
+    /**
+     * @param string|array $redirectType
+     *
+     * @return $this
+     */
+    public function setRedirectType($redirectType)
+    {
+        return $this->_set(UrlRewrite::REDIRECT_TYPE, $redirectType);
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Service/V1/Data/UrlRewrite.php b/app/code/Magento/UrlRedirect/Service/V1/Data/UrlRewrite.php
new file mode 100644
index 0000000000000000000000000000000000000000..a922491f668e77e9789d03555478d2c412c8e99e
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Service/V1/Data/UrlRewrite.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Service\V1\Data;
+
+use Magento\Framework\Service\Data\AbstractObject;
+
+/**
+ * Data abstract class for url storage
+ */
+class UrlRewrite extends AbstractObject
+{
+    /**#@+
+     * Value object attribute names
+     */
+    const ENTITY_ID = 'entity_id';
+    const ENTITY_TYPE = 'entity_type';
+    const REQUEST_PATH = 'request_path';
+    const TARGET_PATH = 'target_path';
+    const STORE_ID = 'store_id';
+    const REDIRECT_TYPE = 'redirect_type';
+    const DESCRIPTION = 'description';
+    /**#@-*/
+
+    /**
+     * Get data by key
+     *
+     * @param string $key
+     * @return mixed|null
+     */
+    public function getByKey($key)
+    {
+        return $this->_get($key);
+    }
+
+    /**
+     * @return int
+     */
+    public function getEntityId()
+    {
+        return $this->_get(self::ENTITY_ID);
+    }
+
+    /**
+     * @return int
+     */
+    public function getEntityType()
+    {
+        return $this->_get(self::ENTITY_TYPE);
+    }
+
+    /**
+     * @return string
+     */
+    public function getRequestPath()
+    {
+        return $this->_get(self::REQUEST_PATH);
+    }
+
+    /**
+     * @return string
+     */
+    public function getTargetPath()
+    {
+        return $this->_get(self::TARGET_PATH);
+    }
+
+    /**
+     * @return int
+     */
+    public function getStoreId()
+    {
+        return $this->_get(self::STORE_ID);
+    }
+
+    /**
+     * @return string
+     */
+    public function getRedirectType()
+    {
+        return $this->_get(self::REDIRECT_TYPE);
+    }
+
+    /**
+     * @return string
+     */
+    public function getDescription()
+    {
+        return $this->_get(self::DESCRIPTION);
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Service/V1/Data/UrlRewriteBuilder.php b/app/code/Magento/UrlRedirect/Service/V1/Data/UrlRewriteBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..e23a3e622a4db79c6a782c3ac7242c8b1c40ecd8
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Service/V1/Data/UrlRewriteBuilder.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Service\V1\Data;
+
+use Magento\Framework\Service\Data\AbstractObjectBuilder;
+
+/**
+ * Data builder class for url rewrite
+ */
+class UrlRewriteBuilder extends AbstractObjectBuilder
+{
+    /**
+     * @param int $entityId
+     *
+     * @return $this
+     */
+    public function setEntityId($entityId)
+    {
+        return $this->_set(UrlRewrite::ENTITY_ID, $entityId);
+    }
+
+    /**
+     * @param int $entityType
+     *
+     * @return $this
+     */
+    public function setEntityType($entityType)
+    {
+        return $this->_set(UrlRewrite::ENTITY_TYPE, $entityType);
+    }
+
+    /**
+     * @param string $requestPath
+     *
+     * @return $this
+     */
+    public function setRequestPath($requestPath)
+    {
+        return $this->_set(UrlRewrite::REQUEST_PATH, $requestPath);
+    }
+
+    /**
+     * @param string $targetPath
+     *
+     * @return $this
+     */
+    public function setTargetPath($targetPath)
+    {
+        return $this->_set(UrlRewrite::TARGET_PATH, $targetPath);
+    }
+
+    /**
+     * @param int $storeId
+     *
+     * @return $this
+     */
+    public function setStoreId($storeId)
+    {
+        return $this->_set(UrlRewrite::STORE_ID, $storeId);
+    }
+
+    /**
+     * @param int $redirectCode
+     *
+     * @return $this
+     */
+    public function setRedirectCode($redirectCode)
+    {
+        return $this->_set(UrlRewrite::REDIRECT_TYPE, $redirectCode);
+    }
+
+    /**
+     * @param string $description
+     *
+     * @return $this
+     */
+    public function setDescription($description)
+    {
+        return $this->_set(UrlRewrite::DESCRIPTION, $description);
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Service/V1/UrlManager.php b/app/code/Magento/UrlRedirect/Service/V1/UrlManager.php
new file mode 100644
index 0000000000000000000000000000000000000000..0e29a14db255388881808f95b946bd90f4be0b3f
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Service/V1/UrlManager.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Service\V1;
+
+use Magento\UrlRedirect\Service\V1\Data\Filter;
+use Magento\UrlRedirect\Service\V1\Data\FilterFactory;
+use Magento\UrlRedirect\Service\V1\Data\UrlRewrite;
+use Magento\UrlRedirect\Model\StorageInterface;
+
+/**
+ * Url Manager
+ */
+class UrlManager implements UrlMatcherInterface, UrlSaveInterface
+{
+    /**
+     * @var StorageInterface
+     */
+    protected $storage;
+
+    /**
+     * @var FilterFactory
+     */
+    protected $filterFactory;
+
+    /**
+     * @param StorageInterface $storage
+     * @param FilterFactory $filterFactory
+     */
+    public function __construct(StorageInterface $storage, FilterFactory $filterFactory)
+    {
+        $this->storage = $storage;
+        $this->filterFactory = $filterFactory;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function save(array $urls)
+    {
+        $this->storage->deleteByFilter($this->createFilter($urls));
+
+        $this->storage->addMultiple($urls);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function match($requestPath, $storeId)
+    {
+        /** @var Filter $filter */
+        $filter = $this->filterFactory->create();
+        $filter->setRequestPath($requestPath)->setStoreId($storeId);
+
+        return $this->findByFilter($filter);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function findByEntity($entityId, $entityType, $storeId = 0)
+    {
+        /** @var Filter $filter */
+        $filter = $this->filterFactory->create();
+        $filter->setEntityId($entityId)->setEntityType($entityType)->setStoreId($storeId);
+
+        return $this->findByFilter($filter);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function findByFilter(Filter $filter)
+    {
+        return $this->storage->findByFilter($filter);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function findAllByFilter(Filter $filter)
+    {
+        return $this->storage->findAllByFilter($filter);
+    }
+
+    /**
+     * Get filter for url rows deletion due to provided urls
+     *
+     * @param UrlRewrite[] $urls
+     * @return Filter
+     */
+    protected function createFilter($urls)
+    {
+        $filterData = [];
+        $uniqueKeys = [UrlRewrite::ENTITY_ID, UrlRewrite::ENTITY_TYPE, UrlRewrite::STORE_ID];
+        foreach ($urls as $url) {
+            foreach ($uniqueKeys as $key) {
+                $fieldValue = $url->getByKey($key);
+
+                if (!isset($filterData[$key]) || !in_array($fieldValue, $filterData[$key])) {
+                    $filterData[$key][] = $fieldValue;
+                }
+            }
+        }
+        return $this->filterFactory->create(['filterData' => $filterData]);
+    }
+}
diff --git a/app/code/Magento/UrlRedirect/Service/V1/UrlMatcherInterface.php b/app/code/Magento/UrlRedirect/Service/V1/UrlMatcherInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ebc555c6947fc9c9286049af1a93b71a2dc473d
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Service/V1/UrlMatcherInterface.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Service\V1;
+
+use Magento\UrlRedirect\Service\V1\Data\Filter;
+
+/**
+ * Url Matcher Interface
+ */
+interface UrlMatcherInterface
+{
+    /**
+     * Match provided request path for store and if matched - return corresponding Data Object
+     *
+     * @param string $requestPath
+     * @param int $storeId
+     * @return \Magento\UrlRedirect\Service\V1\Data\UrlRewrite|null
+     */
+    public function match($requestPath, $storeId);
+
+    /**
+     * Match provided entity for store and if matched - return corresponding Data Object
+     *
+     * @param int $entityId
+     * @param int $entityType
+     * @param int $storeId
+     * @return \Magento\UrlRedirect\Service\V1\Data\UrlRewrite|null
+     */
+    public function findByEntity($entityId, $entityType, $storeId);
+
+    /**
+     * Find row by specific filter
+     *
+     * @param Filter $filter
+     * @return \Magento\UrlRedirect\Service\V1\Data\UrlRewrite|null
+     */
+    public function findByFilter(Filter $filter);
+
+    /**
+     * Find rows by specific filter
+     *
+     * @param Filter $filter
+     * @return \Magento\UrlRedirect\Service\V1\Data\UrlRewrite[]
+     */
+    public function findAllByFilter(Filter $filter);
+}
diff --git a/app/code/Magento/UrlRedirect/Service/V1/UrlSaveInterface.php b/app/code/Magento/UrlRedirect/Service/V1/UrlSaveInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..c07e3b084d26830d4fe2ac2815eaa38bdb557b32
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/Service/V1/UrlSaveInterface.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\UrlRedirect\Service\V1;
+
+/**
+ * Url Save Interface
+ */
+interface UrlSaveInterface
+{
+    /**
+     * Save url rewrites. Return number of saved urls
+     *
+     * @param \Magento\UrlRedirect\Service\V1\Data\UrlRewrite[] $urls
+     * @return void
+     */
+    public function save(array $urls);
+}
diff --git a/app/code/Magento/UrlRedirect/etc/adminhtml/acl.xml b/app/code/Magento/UrlRedirect/etc/adminhtml/acl.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8f2d7946e10928bb4e5fa3d943ad1776f6ad8d7d
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/etc/adminhtml/acl.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/Acl/etc/acl.xsd">
+    <acl>
+        <resources>
+            <resource id="Magento_Adminhtml::admin">
+                <resource id="Magento_Adminhtml::marketing">
+                    <resource id="Magento_Adminhtml::marketing_seo">
+                        <resource id="Magento_UrlRedirect::urlrewrite" title="URL Rewrites" sortOrder="20" />
+                    </resource>
+                </resource>
+            </resource>
+        </resources>
+    </acl>
+</config>
diff --git a/app/code/Magento/UrlRedirect/etc/adminhtml/menu.xml b/app/code/Magento/UrlRedirect/etc/adminhtml/menu.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5ae310d19f71623e70a53f72f79d7dd12ec875ed
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/etc/adminhtml/menu.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../Backend/etc/menu.xsd">
+    <menu>
+        <add id="Magento_UrlRedirect::catalog_urlrewrite" title="URL Rewrites" module="Magento_UrlRedirect"
+             sortOrder="20" parent="Magento_Backend::marketing_seo"
+             action="adminhtml/urlRedirect/index" resource="Magento_UrlRedirect::urlrewrite"/>
+    </menu>
+</config>
diff --git a/app/code/Magento/UrlRedirect/etc/adminhtml/routes.xml b/app/code/Magento/UrlRedirect/etc/adminhtml/routes.xml
new file mode 100644
index 0000000000000000000000000000000000000000..312f40563c2a8e80606cfcd4373ac78a69b30bf5
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/etc/adminhtml/routes.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
+    <router id="admin">
+        <route id="adminhtml">
+            <module name="Magento_UrlRedirect" before="Magento_Adminhtml" />
+        </route>
+    </router>
+</config>
diff --git a/app/code/Magento/UrlRedirect/etc/config.xml b/app/code/Magento/UrlRedirect/etc/config.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c32718649d84f7242780b8740ccc5cf3ff6d28b9
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/etc/config.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Core/etc/config.xsd">
+    <default>
+        <url_rewrite>
+            <entity_types>
+                <product>
+                    <generator>Magento\Framework\Object</generator>
+                </product>
+                <category>
+                    <generator>Magento\Framework\Object</generator>
+                </category>
+                <cms-page>
+                    <generator>Magento\Framework\Object</generator>
+                </cms-page>
+            </entity_types>
+        </url_rewrite>
+    </default>
+</config>
diff --git a/app/code/Magento/UrlRedirect/etc/di.xml b/app/code/Magento/UrlRedirect/etc/di.xml
new file mode 100644
index 0000000000000000000000000000000000000000..888bf6a467b880c2b07f30d927fe89d2ff307246
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/etc/di.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+    <preference for="Magento\UrlRedirect\Model\StorageInterface" type="Magento\UrlRedirect\Model\Storage\Db"/>
+    <preference for="Magento\UrlRedirect\Service\V1\UrlMatcherInterface" type="Magento\UrlRedirect\Service\V1\UrlManager"/>
+    <preference for="Magento\UrlRedirect\Service\V1\UrlSaveInterface" type="Magento\UrlRedirect\Service\V1\UrlManager"/>
+</config>
diff --git a/app/code/Magento/UrlRedirect/etc/frontend/di.xml b/app/code/Magento/UrlRedirect/etc/frontend/di.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7b7acb7b3de3dd0fdeac02e8456261c9fce122ad
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/etc/frontend/di.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+    <type name="Magento\Framework\App\RouterList">
+        <arguments>
+            <argument name="routerList" xsi:type="array">
+                <item name="urlredirect" xsi:type="array">
+                    <item name="class" xsi:type="string">Magento\UrlRedirect\Controller\Router</item>
+                    <item name="disable" xsi:type="boolean">false</item>
+                    <item name="sortOrder" xsi:type="string">40</item>
+                </item>
+            </argument>
+        </arguments>
+    </type>
+</config>
diff --git a/app/code/Magento/UrlRedirect/etc/module.xml b/app/code/Magento/UrlRedirect/etc/module.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1202c64f7285f0189fcdeac1b6e4463c834d4d4f
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/etc/module.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+    <module name="Magento_UrlRedirect" schema_version="1.0.0.0" active="false">
+        <depends>
+            <module name="Magento_Catalog"/>
+            <module name="Magento_Cms"/>
+            <module name="Magento_Core"/>
+            <module name="Magento_Backend"/>
+            <module name="Magento_Install"/>
+            <module name="Magento_Store"/>
+        </depends>
+    </module>
+</config>
diff --git a/app/code/Magento/UrlRedirect/i18n/de_DE.csv b/app/code/Magento/UrlRedirect/i18n/de_DE.csv
new file mode 100644
index 0000000000000000000000000000000000000000..8b6c4909ac30884e66b24d11978dce0e6ec7c71a
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/i18n/de_DE.csv
@@ -0,0 +1,57 @@
+Custom,Custom
+Back,Back
+ID,ID
+SKU,SKU
+No,No
+Action,Action
+Reset,Reset
+Edit,Edit
+"Two and more slashes together are not permitted in request path","Two and more slashes together are not permitted in request path"
+"Anchor symbol (#) is not supported in request path","Anchor symbol (#) is not supported in request path"
+"Request Path for Specified Store","Request Path for Specified Store"
+"Temporary (302)","Temporary (302)"
+"Permanent (301)","Permanent (301)"
+"Edit URL Rewrite for a Category","Edit URL Rewrite for a Category"
+"Add URL Rewrite for a Category","Add URL Rewrite for a Category"
+"Category:","Category:"
+"We can't set up a URL rewrite because the product you chose is not associated with a website.","We can't set up a URL rewrite because the product you chose is not associated with a website."
+"We can't set up a URL rewrite because the category your chose is not associated with a website.","We can't set up a URL rewrite because the category your chose is not associated with a website."
+"Edit URL Rewrite for a Product","Edit URL Rewrite for a Product"
+"Add URL Rewrite for a Product","Add URL Rewrite for a Product"
+"Product:","Product:"
+"Skip Category Selection","Skip Category Selection"
+"Name","Name"
+"Status","Status"
+"Edit URL Rewrite for CMS page","Edit URL Rewrite for CMS page"
+"Add URL Rewrite for CMS page","Add URL Rewrite for CMS page"
+"CMS page:","CMS page:"
+"Chosen cms page does not associated with any website.","Chosen cms page does not associated with any website."
+"Title","Title"
+"URL Key","URL Key"
+"Store View","Store View"
+"Edit URL Rewrite","Edit URL Rewrite"
+"Add New URL Rewrite","Add New URL Rewrite"
+"Delete","Delete"
+"Are you sure you want to do this?","Are you sure you want to do this?"
+"Save","Save"
+"Block Information","Block Information"
+"URL Rewrite Information","URL Rewrite Information"
+"Request Path","Request Path"
+"Target Path","Target Path"
+"Redirect","Redirect"
+"Description","Description"
+"Store","Store"
+"URL Rewrite Management","URL Rewrite Management"
+"Add URL Rewrite","Add URL Rewrite"
+"For category","For category"
+"For product","For product"
+"For CMS page","For CMS page"
+"Create URL Rewrite:","Create URL Rewrite:"
+"URL Rewrites","URL Rewrites"
+"[New/Edit] URL Rewrite","[New/Edit] URL Rewrite"
+"The URL Rewrite has been saved.","The URL Rewrite has been saved."
+"An error occurred while saving URL Rewrite.","An error occurred while saving URL Rewrite."
+"The URL Rewrite has been deleted.","The URL Rewrite has been deleted."
+"An error occurred while deleting URL Rewrite.","An error occurred while deleting URL Rewrite."
+"Select Category","Select Category"
+"Options","Options"
diff --git a/app/code/Magento/UrlRedirect/i18n/en_US.csv b/app/code/Magento/UrlRedirect/i18n/en_US.csv
new file mode 100644
index 0000000000000000000000000000000000000000..2d0c4e9330abff7649b009a699f64e122f41061d
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/i18n/en_US.csv
@@ -0,0 +1,62 @@
+Custom,Custom
+Back,Back
+ID,ID
+SKU,SKU
+No,No
+Custom,Custom
+Back,Back
+ID,ID
+SKU,SKU
+No,No
+Action,Action
+Reset,Reset
+Edit,Edit
+"Two and more slashes together are not permitted in request path","Two and more slashes together are not permitted in request path"
+"Anchor symbol (#) is not supported in request path","Anchor symbol (#) is not supported in request path"
+"Request Path for Specified Store","Request Path for Specified Store"
+"Temporary (302)","Temporary (302)"
+"Permanent (301)","Permanent (301)"
+"Edit URL Rewrite for a Category","Edit URL Rewrite for a Category"
+"Add URL Rewrite for a Category","Add URL Rewrite for a Category"
+"Category:","Category:"
+"We can't set up a URL rewrite because the product you chose is not associated with a website.","We can't set up a URL rewrite because the product you chose is not associated with a website."
+"We can't set up a URL rewrite because the category your chose is not associated with a website.","We can't set up a URL rewrite because the category your chose is not associated with a website."
+"Edit URL Rewrite for a Product","Edit URL Rewrite for a Product"
+"Add URL Rewrite for a Product","Add URL Rewrite for a Product"
+"Product:","Product:"
+"Skip Category Selection","Skip Category Selection"
+"Name","Name"
+"Status","Status"
+"Edit URL Rewrite for CMS page","Edit URL Rewrite for CMS page"
+"Add URL Rewrite for CMS page","Add URL Rewrite for CMS page"
+"CMS page:","CMS page:"
+"Chosen cms page does not associated with any website.","Chosen cms page does not associated with any website."
+"Title","Title"
+"URL Key","URL Key"
+"Store View","Store View"
+"Edit URL Rewrite","Edit URL Rewrite"
+"Add New URL Rewrite","Add New URL Rewrite"
+"Delete","Delete"
+"Are you sure you want to do this?","Are you sure you want to do this?"
+"Save","Save"
+"Block Information","Block Information"
+"URL Rewrite Information","URL Rewrite Information"
+"Request Path","Request Path"
+"Target Path","Target Path"
+"Redirect","Redirect"
+"Description","Description"
+"Store","Store"
+"URL Rewrite Management","URL Rewrite Management"
+"Add URL Rewrite","Add URL Rewrite"
+"For category","For category"
+"For product","For product"
+"For CMS page","For CMS page"
+"Create URL Rewrite:","Create URL Rewrite:"
+"URL Rewrites","URL Rewrites"
+"[New/Edit] URL Rewrite","[New/Edit] URL Rewrite"
+"The URL Rewrite has been saved.","The URL Rewrite has been saved."
+"An error occurred while saving URL Rewrite.","An error occurred while saving URL Rewrite."
+"The URL Rewrite has been deleted.","The URL Rewrite has been deleted."
+"An error occurred while deleting URL Rewrite.","An error occurred while deleting URL Rewrite."
+"Select Category","Select Category"
+"Options","Options"
diff --git a/app/code/Magento/UrlRedirect/i18n/es_ES.csv b/app/code/Magento/UrlRedirect/i18n/es_ES.csv
new file mode 100644
index 0000000000000000000000000000000000000000..8b6c4909ac30884e66b24d11978dce0e6ec7c71a
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/i18n/es_ES.csv
@@ -0,0 +1,57 @@
+Custom,Custom
+Back,Back
+ID,ID
+SKU,SKU
+No,No
+Action,Action
+Reset,Reset
+Edit,Edit
+"Two and more slashes together are not permitted in request path","Two and more slashes together are not permitted in request path"
+"Anchor symbol (#) is not supported in request path","Anchor symbol (#) is not supported in request path"
+"Request Path for Specified Store","Request Path for Specified Store"
+"Temporary (302)","Temporary (302)"
+"Permanent (301)","Permanent (301)"
+"Edit URL Rewrite for a Category","Edit URL Rewrite for a Category"
+"Add URL Rewrite for a Category","Add URL Rewrite for a Category"
+"Category:","Category:"
+"We can't set up a URL rewrite because the product you chose is not associated with a website.","We can't set up a URL rewrite because the product you chose is not associated with a website."
+"We can't set up a URL rewrite because the category your chose is not associated with a website.","We can't set up a URL rewrite because the category your chose is not associated with a website."
+"Edit URL Rewrite for a Product","Edit URL Rewrite for a Product"
+"Add URL Rewrite for a Product","Add URL Rewrite for a Product"
+"Product:","Product:"
+"Skip Category Selection","Skip Category Selection"
+"Name","Name"
+"Status","Status"
+"Edit URL Rewrite for CMS page","Edit URL Rewrite for CMS page"
+"Add URL Rewrite for CMS page","Add URL Rewrite for CMS page"
+"CMS page:","CMS page:"
+"Chosen cms page does not associated with any website.","Chosen cms page does not associated with any website."
+"Title","Title"
+"URL Key","URL Key"
+"Store View","Store View"
+"Edit URL Rewrite","Edit URL Rewrite"
+"Add New URL Rewrite","Add New URL Rewrite"
+"Delete","Delete"
+"Are you sure you want to do this?","Are you sure you want to do this?"
+"Save","Save"
+"Block Information","Block Information"
+"URL Rewrite Information","URL Rewrite Information"
+"Request Path","Request Path"
+"Target Path","Target Path"
+"Redirect","Redirect"
+"Description","Description"
+"Store","Store"
+"URL Rewrite Management","URL Rewrite Management"
+"Add URL Rewrite","Add URL Rewrite"
+"For category","For category"
+"For product","For product"
+"For CMS page","For CMS page"
+"Create URL Rewrite:","Create URL Rewrite:"
+"URL Rewrites","URL Rewrites"
+"[New/Edit] URL Rewrite","[New/Edit] URL Rewrite"
+"The URL Rewrite has been saved.","The URL Rewrite has been saved."
+"An error occurred while saving URL Rewrite.","An error occurred while saving URL Rewrite."
+"The URL Rewrite has been deleted.","The URL Rewrite has been deleted."
+"An error occurred while deleting URL Rewrite.","An error occurred while deleting URL Rewrite."
+"Select Category","Select Category"
+"Options","Options"
diff --git a/app/code/Magento/UrlRedirect/i18n/fr_FR.csv b/app/code/Magento/UrlRedirect/i18n/fr_FR.csv
new file mode 100644
index 0000000000000000000000000000000000000000..8b6c4909ac30884e66b24d11978dce0e6ec7c71a
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/i18n/fr_FR.csv
@@ -0,0 +1,57 @@
+Custom,Custom
+Back,Back
+ID,ID
+SKU,SKU
+No,No
+Action,Action
+Reset,Reset
+Edit,Edit
+"Two and more slashes together are not permitted in request path","Two and more slashes together are not permitted in request path"
+"Anchor symbol (#) is not supported in request path","Anchor symbol (#) is not supported in request path"
+"Request Path for Specified Store","Request Path for Specified Store"
+"Temporary (302)","Temporary (302)"
+"Permanent (301)","Permanent (301)"
+"Edit URL Rewrite for a Category","Edit URL Rewrite for a Category"
+"Add URL Rewrite for a Category","Add URL Rewrite for a Category"
+"Category:","Category:"
+"We can't set up a URL rewrite because the product you chose is not associated with a website.","We can't set up a URL rewrite because the product you chose is not associated with a website."
+"We can't set up a URL rewrite because the category your chose is not associated with a website.","We can't set up a URL rewrite because the category your chose is not associated with a website."
+"Edit URL Rewrite for a Product","Edit URL Rewrite for a Product"
+"Add URL Rewrite for a Product","Add URL Rewrite for a Product"
+"Product:","Product:"
+"Skip Category Selection","Skip Category Selection"
+"Name","Name"
+"Status","Status"
+"Edit URL Rewrite for CMS page","Edit URL Rewrite for CMS page"
+"Add URL Rewrite for CMS page","Add URL Rewrite for CMS page"
+"CMS page:","CMS page:"
+"Chosen cms page does not associated with any website.","Chosen cms page does not associated with any website."
+"Title","Title"
+"URL Key","URL Key"
+"Store View","Store View"
+"Edit URL Rewrite","Edit URL Rewrite"
+"Add New URL Rewrite","Add New URL Rewrite"
+"Delete","Delete"
+"Are you sure you want to do this?","Are you sure you want to do this?"
+"Save","Save"
+"Block Information","Block Information"
+"URL Rewrite Information","URL Rewrite Information"
+"Request Path","Request Path"
+"Target Path","Target Path"
+"Redirect","Redirect"
+"Description","Description"
+"Store","Store"
+"URL Rewrite Management","URL Rewrite Management"
+"Add URL Rewrite","Add URL Rewrite"
+"For category","For category"
+"For product","For product"
+"For CMS page","For CMS page"
+"Create URL Rewrite:","Create URL Rewrite:"
+"URL Rewrites","URL Rewrites"
+"[New/Edit] URL Rewrite","[New/Edit] URL Rewrite"
+"The URL Rewrite has been saved.","The URL Rewrite has been saved."
+"An error occurred while saving URL Rewrite.","An error occurred while saving URL Rewrite."
+"The URL Rewrite has been deleted.","The URL Rewrite has been deleted."
+"An error occurred while deleting URL Rewrite.","An error occurred while deleting URL Rewrite."
+"Select Category","Select Category"
+"Options","Options"
diff --git a/app/code/Magento/UrlRedirect/i18n/nl_NL.csv b/app/code/Magento/UrlRedirect/i18n/nl_NL.csv
new file mode 100644
index 0000000000000000000000000000000000000000..8b6c4909ac30884e66b24d11978dce0e6ec7c71a
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/i18n/nl_NL.csv
@@ -0,0 +1,57 @@
+Custom,Custom
+Back,Back
+ID,ID
+SKU,SKU
+No,No
+Action,Action
+Reset,Reset
+Edit,Edit
+"Two and more slashes together are not permitted in request path","Two and more slashes together are not permitted in request path"
+"Anchor symbol (#) is not supported in request path","Anchor symbol (#) is not supported in request path"
+"Request Path for Specified Store","Request Path for Specified Store"
+"Temporary (302)","Temporary (302)"
+"Permanent (301)","Permanent (301)"
+"Edit URL Rewrite for a Category","Edit URL Rewrite for a Category"
+"Add URL Rewrite for a Category","Add URL Rewrite for a Category"
+"Category:","Category:"
+"We can't set up a URL rewrite because the product you chose is not associated with a website.","We can't set up a URL rewrite because the product you chose is not associated with a website."
+"We can't set up a URL rewrite because the category your chose is not associated with a website.","We can't set up a URL rewrite because the category your chose is not associated with a website."
+"Edit URL Rewrite for a Product","Edit URL Rewrite for a Product"
+"Add URL Rewrite for a Product","Add URL Rewrite for a Product"
+"Product:","Product:"
+"Skip Category Selection","Skip Category Selection"
+"Name","Name"
+"Status","Status"
+"Edit URL Rewrite for CMS page","Edit URL Rewrite for CMS page"
+"Add URL Rewrite for CMS page","Add URL Rewrite for CMS page"
+"CMS page:","CMS page:"
+"Chosen cms page does not associated with any website.","Chosen cms page does not associated with any website."
+"Title","Title"
+"URL Key","URL Key"
+"Store View","Store View"
+"Edit URL Rewrite","Edit URL Rewrite"
+"Add New URL Rewrite","Add New URL Rewrite"
+"Delete","Delete"
+"Are you sure you want to do this?","Are you sure you want to do this?"
+"Save","Save"
+"Block Information","Block Information"
+"URL Rewrite Information","URL Rewrite Information"
+"Request Path","Request Path"
+"Target Path","Target Path"
+"Redirect","Redirect"
+"Description","Description"
+"Store","Store"
+"URL Rewrite Management","URL Rewrite Management"
+"Add URL Rewrite","Add URL Rewrite"
+"For category","For category"
+"For product","For product"
+"For CMS page","For CMS page"
+"Create URL Rewrite:","Create URL Rewrite:"
+"URL Rewrites","URL Rewrites"
+"[New/Edit] URL Rewrite","[New/Edit] URL Rewrite"
+"The URL Rewrite has been saved.","The URL Rewrite has been saved."
+"An error occurred while saving URL Rewrite.","An error occurred while saving URL Rewrite."
+"The URL Rewrite has been deleted.","The URL Rewrite has been deleted."
+"An error occurred while deleting URL Rewrite.","An error occurred while deleting URL Rewrite."
+"Select Category","Select Category"
+"Options","Options"
diff --git a/app/code/Magento/UrlRedirect/i18n/pt_BR.csv b/app/code/Magento/UrlRedirect/i18n/pt_BR.csv
new file mode 100644
index 0000000000000000000000000000000000000000..8b6c4909ac30884e66b24d11978dce0e6ec7c71a
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/i18n/pt_BR.csv
@@ -0,0 +1,57 @@
+Custom,Custom
+Back,Back
+ID,ID
+SKU,SKU
+No,No
+Action,Action
+Reset,Reset
+Edit,Edit
+"Two and more slashes together are not permitted in request path","Two and more slashes together are not permitted in request path"
+"Anchor symbol (#) is not supported in request path","Anchor symbol (#) is not supported in request path"
+"Request Path for Specified Store","Request Path for Specified Store"
+"Temporary (302)","Temporary (302)"
+"Permanent (301)","Permanent (301)"
+"Edit URL Rewrite for a Category","Edit URL Rewrite for a Category"
+"Add URL Rewrite for a Category","Add URL Rewrite for a Category"
+"Category:","Category:"
+"We can't set up a URL rewrite because the product you chose is not associated with a website.","We can't set up a URL rewrite because the product you chose is not associated with a website."
+"We can't set up a URL rewrite because the category your chose is not associated with a website.","We can't set up a URL rewrite because the category your chose is not associated with a website."
+"Edit URL Rewrite for a Product","Edit URL Rewrite for a Product"
+"Add URL Rewrite for a Product","Add URL Rewrite for a Product"
+"Product:","Product:"
+"Skip Category Selection","Skip Category Selection"
+"Name","Name"
+"Status","Status"
+"Edit URL Rewrite for CMS page","Edit URL Rewrite for CMS page"
+"Add URL Rewrite for CMS page","Add URL Rewrite for CMS page"
+"CMS page:","CMS page:"
+"Chosen cms page does not associated with any website.","Chosen cms page does not associated with any website."
+"Title","Title"
+"URL Key","URL Key"
+"Store View","Store View"
+"Edit URL Rewrite","Edit URL Rewrite"
+"Add New URL Rewrite","Add New URL Rewrite"
+"Delete","Delete"
+"Are you sure you want to do this?","Are you sure you want to do this?"
+"Save","Save"
+"Block Information","Block Information"
+"URL Rewrite Information","URL Rewrite Information"
+"Request Path","Request Path"
+"Target Path","Target Path"
+"Redirect","Redirect"
+"Description","Description"
+"Store","Store"
+"URL Rewrite Management","URL Rewrite Management"
+"Add URL Rewrite","Add URL Rewrite"
+"For category","For category"
+"For product","For product"
+"For CMS page","For CMS page"
+"Create URL Rewrite:","Create URL Rewrite:"
+"URL Rewrites","URL Rewrites"
+"[New/Edit] URL Rewrite","[New/Edit] URL Rewrite"
+"The URL Rewrite has been saved.","The URL Rewrite has been saved."
+"An error occurred while saving URL Rewrite.","An error occurred while saving URL Rewrite."
+"The URL Rewrite has been deleted.","The URL Rewrite has been deleted."
+"An error occurred while deleting URL Rewrite.","An error occurred while deleting URL Rewrite."
+"Select Category","Select Category"
+"Options","Options"
diff --git a/app/code/Magento/UrlRedirect/i18n/zh_CN.csv b/app/code/Magento/UrlRedirect/i18n/zh_CN.csv
new file mode 100644
index 0000000000000000000000000000000000000000..8b6c4909ac30884e66b24d11978dce0e6ec7c71a
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/i18n/zh_CN.csv
@@ -0,0 +1,57 @@
+Custom,Custom
+Back,Back
+ID,ID
+SKU,SKU
+No,No
+Action,Action
+Reset,Reset
+Edit,Edit
+"Two and more slashes together are not permitted in request path","Two and more slashes together are not permitted in request path"
+"Anchor symbol (#) is not supported in request path","Anchor symbol (#) is not supported in request path"
+"Request Path for Specified Store","Request Path for Specified Store"
+"Temporary (302)","Temporary (302)"
+"Permanent (301)","Permanent (301)"
+"Edit URL Rewrite for a Category","Edit URL Rewrite for a Category"
+"Add URL Rewrite for a Category","Add URL Rewrite for a Category"
+"Category:","Category:"
+"We can't set up a URL rewrite because the product you chose is not associated with a website.","We can't set up a URL rewrite because the product you chose is not associated with a website."
+"We can't set up a URL rewrite because the category your chose is not associated with a website.","We can't set up a URL rewrite because the category your chose is not associated with a website."
+"Edit URL Rewrite for a Product","Edit URL Rewrite for a Product"
+"Add URL Rewrite for a Product","Add URL Rewrite for a Product"
+"Product:","Product:"
+"Skip Category Selection","Skip Category Selection"
+"Name","Name"
+"Status","Status"
+"Edit URL Rewrite for CMS page","Edit URL Rewrite for CMS page"
+"Add URL Rewrite for CMS page","Add URL Rewrite for CMS page"
+"CMS page:","CMS page:"
+"Chosen cms page does not associated with any website.","Chosen cms page does not associated with any website."
+"Title","Title"
+"URL Key","URL Key"
+"Store View","Store View"
+"Edit URL Rewrite","Edit URL Rewrite"
+"Add New URL Rewrite","Add New URL Rewrite"
+"Delete","Delete"
+"Are you sure you want to do this?","Are you sure you want to do this?"
+"Save","Save"
+"Block Information","Block Information"
+"URL Rewrite Information","URL Rewrite Information"
+"Request Path","Request Path"
+"Target Path","Target Path"
+"Redirect","Redirect"
+"Description","Description"
+"Store","Store"
+"URL Rewrite Management","URL Rewrite Management"
+"Add URL Rewrite","Add URL Rewrite"
+"For category","For category"
+"For product","For product"
+"For CMS page","For CMS page"
+"Create URL Rewrite:","Create URL Rewrite:"
+"URL Rewrites","URL Rewrites"
+"[New/Edit] URL Rewrite","[New/Edit] URL Rewrite"
+"The URL Rewrite has been saved.","The URL Rewrite has been saved."
+"An error occurred while saving URL Rewrite.","An error occurred while saving URL Rewrite."
+"The URL Rewrite has been deleted.","The URL Rewrite has been deleted."
+"An error occurred while deleting URL Rewrite.","An error occurred while deleting URL Rewrite."
+"Select Category","Select Category"
+"Options","Options"
diff --git a/app/code/Magento/UrlRedirect/sql/urlredirect_setup/install-1.0.0.0.php b/app/code/Magento/UrlRedirect/sql/urlredirect_setup/install-1.0.0.0.php
new file mode 100644
index 0000000000000000000000000000000000000000..26f675220af82dc7c905b77ed65d004988eb71c9
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/sql/urlredirect_setup/install-1.0.0.0.php
@@ -0,0 +1,109 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/* @var $installer \Magento\Core\Model\Resource\Setup */
+$installer = $this;
+
+$installer->startSetup();
+
+/**
+ * Create table 'url_rewrite'
+ */
+$table = $installer->getConnection()->newTable(
+    $installer->getTable('url_rewrite')
+)->addColumn(
+    'url_rewrite_id',
+    \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
+    null,
+    array('identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true),
+    'Redirect Id'
+)->addColumn(
+    'entity_id',
+    \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
+    null,
+    array('unsigned' => true, 'nullable' => false),
+    'Entity ID'
+)->addColumn(
+    'entity_type',
+    \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
+    32,
+    array('nullable' => false),
+    'Entity type code'
+)->addColumn(
+    'request_path',
+    \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
+    255,
+    array(),
+    'Request Path'
+)->addColumn(
+    'target_path',
+    \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
+    255,
+    array(),
+    'Target Path'
+)->addColumn(
+    'redirect_type',
+    \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
+    2,
+    array('nullable' => true),
+    'Redirect Type'
+)->addColumn(
+    'store_id',
+    \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
+    null,
+    array('unsigned' => true, 'nullable' => false, 'default' => '0'),
+    'Store Id'
+)->addColumn(
+    'description',
+    \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
+    255,
+    array(),
+    'Description'
+)->addIndex(
+    $installer->getIdxName(
+        'url_rewrite',
+        array('request_path', 'store_id'),
+        \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE
+    ),
+    array('request_path', 'store_id'),
+    array('type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE)
+)->addIndex(
+    $installer->getIdxName('url_rewrite', array('target_path', 'store_id')),
+    array('target_path', 'store_id')
+)->addIndex(
+    $installer->getIdxName('url_rewrite', array('store_id')),
+    array('store_id')
+)->addForeignKey(
+    $installer->getFkName('url_rewrite', 'store_id', 'store', 'store_id'),
+    'store_id',
+    $installer->getTable('store'),
+    'store_id',
+    \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE,
+    \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
+)->setComment(
+    'Url Rewrites'
+);
+$installer->getConnection()->createTable($table);
+
+$installer->endSetup();
diff --git a/app/code/Magento/UrlRedirect/view/adminhtml/layout/adminhtml_urlredirect_index.xml b/app/code/Magento/UrlRedirect/view/adminhtml/layout/adminhtml_urlredirect_index.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6fc0be6b9568fe91470f7552423960da8c70939e
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/view/adminhtml/layout/adminhtml_urlredirect_index.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Core/etc/layout_single.xsd">
+    <referenceContainer name="content">
+        <block class="Magento\UrlRedirect\Block\GridContainer" name="adminhtml.block.urlredirect.grid.container">
+            <block class="Magento\Backend\Block\Widget\Grid" name="adminhtml.block.urlredirect.grid" as="grid">
+                <arguments>
+                    <argument name="id" xsi:type="string">urlredirectGrid</argument>
+                    <argument name="dataSource" xsi:type="object">Magento\UrlRedirect\Model\Resource\UrlRedirect\Collection</argument>
+                    <argument name="default_sort" xsi:type="string">url_rewrite_id</argument>
+                </arguments>
+                <block class="Magento\Backend\Block\Widget\Grid\ColumnSet" as="grid.columnSet" name="adminhtml.urlredirect.grid.columnSet">
+                    <arguments>
+                        <argument name="rowUrl" xsi:type="array">
+                            <item name="path" xsi:type="string">adminhtml/*/edit</item>
+                            <item name="extraParamsTemplate" xsi:type="array">
+                                <item name="id" xsi:type="string">getId</item>
+                            </item>
+                        </argument>
+                    </arguments>
+                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="url_rewrite_id">
+                        <arguments>
+                            <argument name="header" xsi:type="string" translate="true">ID</argument>
+                            <argument name="type" xsi:type="string">text</argument>
+                            <argument name="id" xsi:type="string">url_rewrite_id</argument>
+                            <argument name="index" xsi:type="string">url_rewrite_id</argument>
+                            <argument name="column_css_class" xsi:type="string">col-id</argument>
+                            <argument name="header_css_class" xsi:type="string">col-id</argument>
+                        </arguments>
+                    </block>
+                    <block class="Magento\Backend\Block\Widget\Grid\Column\Multistore" as="store_id">
+                        <arguments>
+                            <argument name="header" xsi:type="string" translate="true">Store View</argument>
+                            <argument name="type" xsi:type="string">store</argument>
+                            <argument name="id" xsi:type="string">store_id</argument>
+                            <argument name="index" xsi:type="string">store_id</argument>
+                            <argument name="store_view" xsi:type="string">true</argument>
+                        </arguments>
+                    </block>
+                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="request_path">
+                        <arguments>
+                            <argument name="header" xsi:type="string" translate="true">Request Path</argument>
+                            <argument name="type" xsi:type="string">text</argument>
+                            <argument name="id" xsi:type="string">request_path</argument>
+                            <argument name="index" xsi:type="string">request_path</argument>
+                        </arguments>
+                    </block>
+                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="target_path">
+                        <arguments>
+                            <argument name="header" xsi:type="string" translate="true">Target Path</argument>
+                            <argument name="type" xsi:type="string">text</argument>
+                            <argument name="id" xsi:type="string">target_path</argument>
+                            <argument name="index" xsi:type="string">target_path</argument>
+                        </arguments>
+                    </block>
+                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="options">
+                        <arguments>
+                            <argument name="header" xsi:type="string" translate="true">Options</argument>
+                            <argument name="type" xsi:type="string">text</argument>
+                            <argument name="id" xsi:type="string">options</argument>
+                            <argument name="index" xsi:type="string">options</argument>
+                        </arguments>
+                    </block>
+                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="actions">
+                        <arguments>
+                            <argument name="header" xsi:type="string" translate="true">Action</argument>
+                            <argument name="sortable" xsi:type="string">0</argument>
+                            <argument name="filter" xsi:type="string">0</argument>
+                            <argument name="type" xsi:type="string">action</argument>
+                            <argument name="id" xsi:type="string">actions</argument>
+                            <argument name="index" xsi:type="string">url_rewrite_id</argument>
+                            <argument name="actions" xsi:type="array">
+                                <item name="view_action" xsi:type="array">
+                                    <item name="caption" xsi:type="string" translate="true">Edit</item>
+                                    <item name="url" xsi:type="array">
+                                        <item name="base" xsi:type="string">adminhtml/*/edit</item>
+                                    </item>
+                                    <item name="field" xsi:type="string">id</item>
+                                </item>
+                            </argument>
+                        </arguments>
+                    </block>
+                </block>
+            </block>
+        </block>
+    </referenceContainer>
+</layout>
diff --git a/app/code/Magento/UrlRedirect/view/adminhtml/templates/categories.phtml b/app/code/Magento/UrlRedirect/view/adminhtml/templates/categories.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..c5888579d548182941371bb14e823b3c2e35ef8d
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/view/adminhtml/templates/categories.phtml
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+/** @var $this \Magento\UrlRedirect\Block\Catalog\Category\Tree */
+?>
+<fieldset class="fieldset" data-ui-id="category-selector">
+    <legend class="legend"><span><?php echo __('Select Category') ?></span></legend>
+    <div class="content" style="clear: both;">
+        <input type="hidden" name="categories" id="product_categories" value="" />
+        <?php if ($this->getRoot()): ?>
+        <div data-mage-init='<?php
+            echo $this->escapeHtml($this->helper('Magento\Core\Helper\Data')->jsonEncode(array(
+                'categoryTree' => array(
+                    'data' => $this->getTreeArray(null),
+                    'url' => $this->getLoadTreeUrl(),
+                )
+            )));
+        ?>' class="jstree-default"></div>
+        <?php endif; ?>
+    </div>
+</fieldset>
diff --git a/app/code/Magento/UrlRedirect/view/adminhtml/templates/edit.phtml b/app/code/Magento/UrlRedirect/view/adminhtml/templates/edit.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..74cd2357bdc527dc6444d805acbebb99e229cc48
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/view/adminhtml/templates/edit.phtml
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+
+/**
+ * Urlrewrites edit container
+ *
+ * @var $this \Magento\UrlRedirect\Block\Edit
+ */
+?>
+<?php echo $this->getChildHtml() ?>
+
+<?php if ($this->getChildBlock('form')): ?>
+<script type="text/javascript">
+    jQuery('#edit_form').mage('form')
+        .mage('validation', {validationUrl: '<?php echo $this->getValidationUrl() ?>'});
+</script>
+<?php endif; ?>
diff --git a/app/code/Magento/UrlRedirect/view/adminhtml/templates/selector.phtml b/app/code/Magento/UrlRedirect/view/adminhtml/templates/selector.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..c6db4f73ad984213ef5aee0e07b0c4be58c768e8
--- /dev/null
+++ b/app/code/Magento/UrlRedirect/view/adminhtml/templates/selector.phtml
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+/** @var $this \Magento\UrlRedirect\Block\Selector */
+?>
+<div class="form-inline">
+    <fieldset class="fieldset" data-ui-id="entity-type-selector">
+        <div class="field field-url-rewrite-option-select">
+            <label for="url-rewrite-option-select" class="label"><?php echo $this->getSelectorLabel() ?></label>
+            <div class="control">
+                <?php $url = $this->helper('Magento\Backend\Helper\Data')->getUrl('adminhtml/*/*')?>
+                <select id="url-rewrite-option-select" class="select" onchange="window.location = this.value;">
+                <?php foreach ($this->getModes() as $mode => $label): ?>
+                    <option <?php echo ($this->isMode($mode) ? 'selected="selected" ' :'' ) ?>value="<?php echo $url . $mode ?>"><?php echo $label ?></option>
+                <?php endforeach; ?>
+                </select>
+            </div>
+        </div>
+    </fieldset>
+</div>
diff --git a/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php b/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php
index 1a35175e4bdfb2e6a3e85835c6e05e9c46be188d..027a5e93445a3b63e0e86c2e04f07453c8f1d400 100644
--- a/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php
+++ b/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php
@@ -61,6 +61,11 @@ class Generator
      */
     protected $_registeredTypes = array();
 
+    /**
+     * @var \Magento\Store\Model\StoreManagerInterface
+     */
+    protected $storeManager;
+
     /**
      * Initialize dependencies.
      *
@@ -68,17 +73,20 @@ class Generator
      * @param Factory $wsdlFactory
      * @param \Magento\Webapi\Model\Cache\Type $cache
      * @param \Magento\Webapi\Model\Config\ClassReflector\TypeProcessor $typeProcessor
+     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
      */
     public function __construct(
         \Magento\Webapi\Model\Soap\Config $apiConfig,
         Factory $wsdlFactory,
         \Magento\Webapi\Model\Cache\Type $cache,
-        \Magento\Webapi\Model\Config\ClassReflector\TypeProcessor $typeProcessor
+        \Magento\Webapi\Model\Config\ClassReflector\TypeProcessor $typeProcessor,
+        \Magento\Store\Model\StoreManagerInterface $storeManager
     ) {
         $this->_apiConfig = $apiConfig;
         $this->_wsdlFactory = $wsdlFactory;
         $this->_cache = $cache;
         $this->_typeProcessor = $typeProcessor;
+        $this->storeManager = $storeManager;
     }
 
     /**
@@ -93,7 +101,8 @@ class Generator
     {
         /** Sort requested services by names to prevent caching of the same wsdl file more than once. */
         ksort($requestedServices);
-        $cacheId = self::WSDL_CACHE_ID . hash('md5', serialize($requestedServices));
+        $currentStore = $this->storeManager->getStore();
+        $cacheId = self::WSDL_CACHE_ID . hash('md5', serialize($requestedServices) . $currentStore->getCode());
         $cachedWsdlContent = $this->_cache->load($cacheId);
         if ($cachedWsdlContent !== false) {
             return $cachedWsdlContent;
diff --git a/app/code/Magento/Weee/Model/Config.php b/app/code/Magento/Weee/Model/Config.php
index 0cc476aa9605d0125aa2f1b338f7e5d9b59d8051..e832c4940b5199f937a9fcbe4fa4cf254e3c9565 100644
--- a/app/code/Magento/Weee/Model/Config.php
+++ b/app/code/Magento/Weee/Model/Config.php
@@ -35,6 +35,22 @@ class Config
      */
     const XML_PATH_FPT_ENABLED = 'tax/weee/enable';
 
+    // display settings
+    const XML_PATH_FPT_DISPLAY_PRODUCT_VIEW = 'tax/weee/display';
+
+    const XML_PATH_FPT_DISPLAY_PRODUCT_LIST = 'tax/weee/display_list';
+
+    const XML_PATH_FPT_DISPLAY_SALES = 'tax/weee/display_sales';
+
+    const XML_PATH_FPT_DISPLAY_EMAIL = 'tax/weee/display_email';
+
+    // misc
+    const XML_PATH_FPT_INCLUDE_IN_SUBTOTAL = 'tax/weee/include_in_subtotal';
+
+    const XML_PATH_FPT_DISCOUNTED = 'tax/weee/discount';
+
+    const XML_PATH_FPT_TAXABLE = 'tax/weee/apply_vat';
+
     /**
      * Core store config
      *
@@ -63,7 +79,7 @@ class Config
     public function getPriceDisplayType($store = null)
     {
         return $this->scopeConfig->getValue(
-            'tax/weee/display',
+            self::XML_PATH_FPT_DISPLAY_PRODUCT_VIEW,
             \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
             $store
         );
@@ -78,7 +94,7 @@ class Config
     public function getListPriceDisplayType($store = null)
     {
         return $this->scopeConfig->getValue(
-            'tax/weee/display_list',
+            self::XML_PATH_FPT_DISPLAY_PRODUCT_LIST,
             \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
             $store
         );
@@ -93,7 +109,7 @@ class Config
     public function getSalesPriceDisplayType($store = null)
     {
         return $this->scopeConfig->getValue(
-            'tax/weee/display_sales',
+            self::XML_PATH_FPT_DISPLAY_SALES,
             \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
             $store
         );
@@ -108,7 +124,7 @@ class Config
     public function getEmailPriceDisplayType($store = null)
     {
         return $this->scopeConfig->getValue(
-            'tax/weee/display_email',
+            self::XML_PATH_FPT_DISPLAY_EMAIL,
             \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
             $store
         );
@@ -139,7 +155,7 @@ class Config
     public function includeInSubtotal($store = null)
     {
         return $this->scopeConfig->isSetFlag(
-            'tax/weee/include_in_subtotal',
+            self::XML_PATH_FPT_INCLUDE_IN_SUBTOTAL,
             \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
             $store
         );
@@ -154,7 +170,7 @@ class Config
     public function isDiscounted($store = null)
     {
         return $this->scopeConfig->isSetFlag(
-            'tax/weee/discount',
+            self::XML_PATH_FPT_DISCOUNTED,
             \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
             $store
         );
@@ -169,7 +185,7 @@ class Config
     public function isTaxable($store = null)
     {
         return $this->scopeConfig->isSetFlag(
-            'tax/weee/apply_vat',
+            self::XML_PATH_FPT_TAXABLE,
             \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
             $store
         );
diff --git a/app/code/Magento/Weee/Model/Total/Quote/Weee.php b/app/code/Magento/Weee/Model/Total/Quote/Weee.php
index 5b9e38184a26ffc8036235b3e68aac28083d0da3..b03e4c08bb0880c47728135c02f01ca55b73ae39 100644
--- a/app/code/Magento/Weee/Model/Total/Quote/Weee.php
+++ b/app/code/Magento/Weee/Model/Total/Quote/Weee.php
@@ -25,43 +25,53 @@ namespace Magento\Weee\Model\Total\Quote;
 
 use Magento\Store\Model\Store;
 use Magento\Tax\Model\Calculation;
+use Magento\Sales\Model\Quote\Address\Total\AbstractTotal;
+use Magento\Tax\Model\Sales\Total\Quote\CommonTaxCollector;
 
-class Weee extends \Magento\Tax\Model\Sales\Total\Quote\Tax
+class Weee extends CommonTaxCollector
 {
+    /**
+     * Constant for weee item code prefix
+     */
+    const ITEM_CODE_WEEE_PREFIX = 'weee';
+    /**
+     * Constant for weee item type
+     */
+    const ITEM_TYPE = 'weee';
+
     /**
      * @var \Magento\Weee\Helper\Data
      */
-    protected $_weeeData;
-    
+    protected $weeeData;
+
     /**
      * @var \Magento\Store\Model\Store
      */
     protected $_store;
 
     /**
-     * @var \Magento\Tax\Model\Calculation
+     * Static counter
+     *
+     * @var int
      */
-    protected $_calculator;
+    protected static $counter = 0;
+
+    /**
+     * Array to keep track of weee taxable item code to quote item
+     *
+     * @var array
+     */
+    protected $weeeCodeToItemMap;
+
     /**
-     * @param \Magento\Tax\Helper\Data $taxData
-     * @param \Magento\Tax\Model\Config $taxConfig
-     * @param \Magento\Tax\Service\V1\TaxCalculationService $taxCalculationService
-     * @param \Magento\Tax\Service\V1\Data\QuoteDetailsBuilder $quoteDetailsBuilder
-     * @param \Magento\Tax\Model\Calculation $calculation
      * @param \Magento\Weee\Helper\Data $weeeData
      */
     public function __construct(
-        \Magento\Tax\Helper\Data $taxData,
-        \Magento\Tax\Model\Config $taxConfig,
-        \Magento\Tax\Service\V1\TaxCalculationService $taxCalculationService,
-        \Magento\Tax\Service\V1\Data\QuoteDetailsBuilder $quoteDetailsBuilder,
-        \Magento\Tax\Model\Calculation $calculation,
         \Magento\Weee\Helper\Data $weeeData
     ) {
-        $this->_weeeData = $weeeData;
-        $this->_calculator = $calculation;
-        parent::__construct($taxData, $taxConfig, $taxCalculationService, $quoteDetailsBuilder);
+        $this->weeeData = $weeeData;
         $this->setCode('weee');
+        $this->weeeCodeToItemMap = [];
     }
 
     /**
@@ -72,16 +82,17 @@ class Weee extends \Magento\Tax\Model\Sales\Total\Quote\Tax
      */
     public function collect(\Magento\Sales\Model\Quote\Address $address)
     {
-        \Magento\Sales\Model\Quote\Address\Total\AbstractTotal::collect($address);
+        AbstractTotal::collect($address);
+        $this->_store = $address->getQuote()->getStore();
+        if (!$this->weeeData->isEnabled($this->_store)) {
+            return $this;
+        }
+
         $items = $this->_getAddressItems($address);
         if (!count($items)) {
             return $this;
         }
 
-        $address->setAppliedTaxesReset(true);
-        $address->setAppliedTaxes(array());
-
-        $this->_store = $address->getQuote()->getStore();
         foreach ($items as $item) {
             if ($item->getParentItemId()) {
                 continue;
@@ -98,6 +109,7 @@ class Weee extends \Magento\Tax\Model\Sales\Total\Quote\Tax
             }
         }
 
+        $address->setWeeeCodeToItemMap($this->weeeCodeToItemMap);
         return $this;
     }
 
@@ -110,28 +122,15 @@ class Weee extends \Magento\Tax\Model\Sales\Total\Quote\Tax
      */
     protected function _process(\Magento\Sales\Model\Quote\Address $address, $item)
     {
-        if (!$this->_weeeData->isEnabled($this->_store)) {
-            return $this;
-        }
-
-        $attributes = $this->_weeeData->getProductWeeeAttributes(
+        $attributes = $this->weeeData->getProductWeeeAttributes(
             $item->getProduct(),
             $address,
             $address->getQuote()->getBillingAddress(),
             $this->_store->getWebsiteId()
         );
 
-        $applied = array();
         $productTaxes = array();
 
-        $defaultRateRequest = $this->_calculator->getRateOriginRequest($this->_store);
-        $rateRequest = $this->_calculator->getRateRequest(
-            $address,
-            $address->getQuote()->getBillingAddress(),
-            $address->getQuote()->getCustomerTaxClassId(),
-            $this->_store
-        );
-
         $totalValueInclTax = 0;
         $baseTotalValueInclTax = 0;
         $totalRowValueInclTax = 0;
@@ -142,60 +141,19 @@ class Weee extends \Magento\Tax\Model\Sales\Total\Quote\Tax
         $totalRowValueExclTax = 0;
         $baseTotalRowValueExclTax = 0;
 
-        $priceIncludesTax = $this->_taxData->priceIncludesTax($this->_store);
-        $calculationAlgorithm = $this->_taxData->getCalculationAgorithm($this->_store);
-        $defaultPercent = $currentPercent = 0; //when FPT is not taxable
+        $associatedTaxables = $item->getAssociatedTaxables();
+        if (!$associatedTaxables) {
+            $associatedTaxables = [];
+        }
         foreach ($attributes as $key => $attribute) {
             $title          = $attribute->getName();
 
-            $baseValue = $attribute->getAmount();
-            $value = $this->_store->convertPrice($baseValue);
-            $value = $this->_store->roundPrice($value);
-
-            if ($this->_weeeData->isTaxable($this->_store)) {
-                $defaultPercent = $this->_calculator->getRate(
-                    $defaultRateRequest->setProductClassId($item->getProduct()->getTaxClassId())
-                );
-                $currentPercent = $this->_calculator->getRate(
-                    $rateRequest->setProductClassId($item->getProduct()->getTaxClassId())
-                );
-            }
-
-            if ($priceIncludesTax) {
-                //Make sure that price including tax is rounded first
-                $baseValueInclTax = $baseValue / (100 + $defaultPercent) * (100 + $currentPercent);
-                $baseValueInclTax = $this->_store->roundPrice($baseValueInclTax);
-                $valueInclTax = $value / (100 + $defaultPercent) * (100 + $currentPercent);
-                $valueInclTax = $this->_store->roundPrice($valueInclTax);
-
-                $baseValueExclTax = $baseValueInclTax / (100 + $currentPercent) * 100;
-                $valueExclTax = $valueInclTax / (100 + $currentPercent) * 100;
-                if ($calculationAlgorithm == Calculation::CALC_UNIT_BASE) {
-                    $baseValueExclTax = $this->_store->roundPrice($baseValueExclTax);
-                    $valueExclTax = $this->_store->roundPrice($valueExclTax);
-                }
-            } else {
-                $valueExclTax = $value;
-                $baseValueExclTax = $baseValue;
-
-                $valueInclTax = $valueExclTax * (100 + $currentPercent) / 100;
-                $baseValueInclTax = $baseValueExclTax * (100 + $currentPercent) / 100;
-                if ($calculationAlgorithm == Calculation::CALC_UNIT_BASE) {
-                    $baseValueInclTax = $this->_store->roundPrice($baseValueInclTax);
-                    $valueInclTax = $this->_store->roundPrice($valueInclTax);
-                }
-            }
-
-            $rowValueInclTax       = $this->_store->roundPrice($valueInclTax * $item->getTotalQty());
-            $baseRowValueInclTax   = $this->_store->roundPrice($baseValueInclTax * $item->getTotalQty());
-            $rowValueExclTax = $this->_store->roundPrice($valueExclTax * $item->getTotalQty());
-            $baseRowValueExclTax = $this->_store->roundPrice($baseValueExclTax * $item->getTotalQty());
+            $baseValueExclTax = $baseValueInclTax = $attribute->getAmount();
+            $valueExclTax = $valueInclTax = $this->_store->roundPrice($this->_store->convertPrice($baseValueExclTax));
 
-            //Now, round the unit price just in case
-            $valueExclTax = $this->_store->roundPrice($valueExclTax);
-            $baseValueExclTax = $this->_store->roundPrice($baseValueExclTax);
-            $valueInclTax = $this->_store->roundPrice($valueInclTax);
-            $baseValueInclTax = $this->_store->roundPrice($baseValueInclTax);
+            $rowValueInclTax = $rowValueExclTax = $this->_store->roundPrice($valueInclTax * $item->getTotalQty());
+            $baseRowValueInclTax = $this->_store->roundPrice($baseValueInclTax * $item->getTotalQty());
+            $baseRowValueExclTax = $baseRowValueInclTax;
 
             $totalValueInclTax += $valueInclTax;
             $baseTotalValueInclTax += $baseValueInclTax;
@@ -220,23 +178,22 @@ class Weee extends \Magento\Tax\Model\Sales\Total\Quote\Tax
                 'base_row_amount_incl_tax' => $baseRowValueInclTax,
             );
 
-            //This include FPT as applied tax, since tax on FPT is calculated separately, we use value excluding tax
-            $applied[] = array(
-                'id'        => $attribute->getCode(),
-                'percent'   => null,
-                'hidden'    => $this->_weeeData->includeInSubtotal($this->_store),
-                'rates'     => array(array(
-                    'base_real_amount'=> $baseRowValueExclTax,
-                    'base_amount'   => $baseRowValueExclTax,
-                    'amount'        => $rowValueExclTax,
-                    'code'          => $attribute->getCode(),
-                    'title'         => $title,
-                    'percent'       => null,
-                    'position'      => 1,
-                    'priority'      => -1000 + $key,
-                ))
-            );
+            if ($this->weeeData->isTaxable($this->_store)) {
+                $itemTaxCalculationId = $item->getTaxCalculationItemId();
+                $weeeItemCode = self::ITEM_CODE_WEEE_PREFIX . $this->getNextIncrement();
+                $weeeItemCode .= '-' . $title;
+                $associatedTaxables[] = [
+                    self::KEY_ASSOCIATED_TAXABLE_TYPE => self::ITEM_TYPE,
+                    self::KEY_ASSOCIATED_TAXABLE_CODE => $weeeItemCode,
+                    self::KEY_ASSOCIATED_TAXABLE_UNIT_PRICE => $valueExclTax,
+                    self::KEY_ASSOCIATED_TAXABLE_BASE_UNIT_PRICE => $baseValueExclTax,
+                    self::KEY_ASSOCIATED_TAXABLE_QUANTITY => $item->getQty(),
+                    self::KEY_ASSOCIATED_TAXABLE_TAX_CLASS_ID => $item->getProduct()->getTaxClassId(),
+                ];
+                $this->weeeCodeToItemMap[$weeeItemCode] = $item;
+            }
         }
+        $item->setAssociatedTaxables($associatedTaxables);
 
         $item->setWeeeTaxAppliedAmount($totalValueExclTax)
             ->setBaseWeeeTaxAppliedAmount($baseTotalValueExclTax)
@@ -248,24 +205,7 @@ class Weee extends \Magento\Tax\Model\Sales\Total\Quote\Tax
             ->setWeeeTaxAppliedRowAmountInclTax($totalRowValueInclTax)
             ->setBaseWeeeTaxAppliedRowAmntInclTax($baseTotalRowValueInclTax);
 
-        if ($priceIncludesTax) {
-            $this->_processTaxSettings(
-                $item,
-                $totalValueInclTax,
-                $baseTotalValueInclTax,
-                $totalRowValueInclTax,
-                $baseTotalRowValueInclTax
-            );
-        } else {
-            $this->_processTaxSettings(
-                $item,
-                $totalValueExclTax,
-                $baseTotalValueExclTax,
-                $totalRowValueExclTax,
-                $baseTotalRowValueExclTax
-            );
-        }
-        $this->_processTotalAmount(
+        $this->processTotalAmount(
             $address,
             $totalRowValueExclTax,
             $baseTotalRowValueExclTax,
@@ -273,56 +213,7 @@ class Weee extends \Magento\Tax\Model\Sales\Total\Quote\Tax
             $baseTotalRowValueInclTax
         );
 
-        $this->_weeeData->setApplied($item, array_merge($this->_weeeData->getApplied($item), $productTaxes));
-
-        //Update the applied taxes for the quote
-        if ($applied) {
-            $this->_saveAppliedTaxes(
-                $address,
-                $applied,
-                $item->getWeeeTaxAppliedAmount(),
-                $item->getBaseWeeeTaxAppliedAmount(),
-                null
-            );
-        }
-    }
-
-    /**
-     * Check if discount should be applied to weee and add weee to discounted price
-     *
-     * @deprecated 
-     * @param   \Magento\Sales\Model\Quote\Item\AbstractItem $item
-     * @param   float $value
-     * @param   float $baseValue
-     * @return  $this
-     */
-    protected function _processDiscountSettings($item, $value, $baseValue)
-    {
-        if ($this->_weeeData->isDiscounted($this->_store)) {
-            $this->_weeeData->addItemDiscountPrices($item, $baseValue, $value);
-        }
-        return $this;
-    }
-
-    /**
-     * Add extra amount which should be taxable by regular tax
-     *
-     * @param   \Magento\Sales\Model\Quote\Item\AbstractItem $item
-     * @param   float $value
-     * @param   float $baseValue
-     * @param   float $rowValue
-     * @param   float $baseRowValue
-     * @return  $this
-     */
-    protected function _processTaxSettings($item, $value, $baseValue, $rowValue, $baseRowValue)
-    {
-        if ($this->_weeeData->isTaxable($this->_store) && $rowValue) {
-            $item->setExtraTaxableAmount($value)
-                ->setBaseExtraTaxableAmount($baseValue)
-                ->setExtraRowTaxableAmount($rowValue)
-                ->setBaseExtraRowTaxableAmount($baseRowValue);
-        }
-        return $this;
+        $this->weeeData->setApplied($item, array_merge($this->weeeData->getApplied($item), $productTaxes));
     }
 
     /**
@@ -335,24 +226,38 @@ class Weee extends \Magento\Tax\Model\Sales\Total\Quote\Tax
      * @param   float $baseRowValueInclTax
      * @return  $this
      */
-    protected function _processTotalAmount($address, $rowValueExclTax, $baseRowValueExclTax, $rowValueInclTax, $baseRowValueInclTax)
+    protected function processTotalAmount($address, $rowValueExclTax, $baseRowValueExclTax, $rowValueInclTax, $baseRowValueInclTax)
     {
-        //TODO: use tax service to calculate tax
-        if ($this->_weeeData->includeInSubtotal($this->_store)) {
-            $address->setExtraSubtotalAmount($this->_store->roundPrice($rowValueExclTax));
-            $address->setBaseExtraSubtotalAmount($this->_store->roundPrice($baseRowValueExclTax));
-        } else {
-            $address->addTotalAmount('weee', $rowValueExclTax);
-            $address->addBaseTotalAmount('weee', $baseRowValueExclTax);
+        if (!$this->weeeData->isTaxable($this->_store)) {
+            //otherwise, defer to weee_tax collector to update subtotal and tax
+            if ($this->weeeData->includeInSubtotal($this->_store)) {
+                $address->addTotalAmount('subtotal', $this->_store->roundPrice($rowValueExclTax));
+                $address->addBaseTotalAmount('subtotal', $this->_store->roundPrice($baseRowValueExclTax));
+            } else {
+                $address->addTotalAmount('weee', $rowValueExclTax);
+                $address->addBaseTotalAmount('weee', $baseRowValueExclTax);
+            }
         }
-        $address->setExtraTaxAmount($rowValueInclTax - $rowValueExclTax);
-        $address->setBaseExtraTaxAmount($baseRowValueInclTax - $baseRowValueExclTax);
-
+        
+        //This value is used to calculate shipping cost, it will be overridden by tax collector
         $address->setSubtotalInclTax($address->getSubtotalInclTax() + $this->_store->roundPrice($rowValueInclTax));
-        $address->setBaseSubtotalInclTax($address->getBaseSubtotalInclTax() + $this->_store->roundPrice($baseRowValueInclTax));
+        $address->setBaseSubtotalInclTax(
+            $address->getBaseSubtotalInclTax() + $this->_store->roundPrice($baseRowValueInclTax)
+        );
         return $this;
     }
 
+    /**
+     * Increment and return static counter. This function is intended to be used to generate temporary
+     * id for an item.
+     *
+     * @return int
+     */
+    protected function getNextIncrement()
+    {
+        return ++self::$counter;
+    }
+
     /**
      * Recalculate parent item amounts based on children results
      *
@@ -373,7 +278,7 @@ class Weee extends \Magento\Tax\Model\Sales\Total\Quote\Tax
      */
     protected function _resetItemData($item)
     {
-        $this->_weeeData->setApplied($item, array());
+        $this->weeeData->setApplied($item, array());
 
         $item->setBaseWeeeTaxDisposition(0);
         $item->setWeeeTaxDisposition(0);
@@ -389,28 +294,13 @@ class Weee extends \Magento\Tax\Model\Sales\Total\Quote\Tax
     }
 
     /**
-     * Fetch the Weee total amount for display in totals block when building the initial quote
+     * Delegate this to WeeeTax collector
      *
      * @param   \Magento\Sales\Model\Quote\Address $address
      * @return  $this
      */
     public function fetch(\Magento\Sales\Model\Quote\Address $address)
     {
-        /** @var $items \Magento\Sales\Model\Order\Item[] */
-        $items = $this->_getAddressItems($address);
-        $store = $address->getQuote()->getStore();
-
-        $weeeTotal = $this->_weeeData->getTotalAmounts($items, $store);
-        if ($weeeTotal) {
-            $address->addTotal(
-                array(
-                    'code' => $this->getCode(),
-                    'title' => __('FPT'),
-                    'value' => $weeeTotal,
-                    'area' => null
-                )
-            );
-        }
         return $this;
     }
 
diff --git a/app/code/Magento/Weee/Model/Total/Quote/WeeeTax.php b/app/code/Magento/Weee/Model/Total/Quote/WeeeTax.php
new file mode 100644
index 0000000000000000000000000000000000000000..e947c88e53957a123498415df80d74fa512f997e
--- /dev/null
+++ b/app/code/Magento/Weee/Model/Total/Quote/WeeeTax.php
@@ -0,0 +1,192 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Weee\Model\Total\Quote;
+
+use Magento\Store\Model\Store;
+use Magento\Tax\Model\Calculation;
+use Magento\Sales\Model\Quote\Address\Total\AbstractTotal;
+use Magento\Tax\Model\Sales\Total\Quote\CommonTaxCollector;
+
+class WeeeTax extends Weee
+{
+    /**
+     * Collect Weee taxes amount and prepare items prices for taxation and discount
+     *
+     * @param   \Magento\Sales\Model\Quote\Address $address
+     * @return  $this
+     */
+    public function collect(\Magento\Sales\Model\Quote\Address $address)
+    {
+        \Magento\Sales\Model\Quote\Address\Total\AbstractTotal::collect($address);
+        $this->store = $address->getQuote()->getStore();
+        if (!$this->weeeData->isEnabled($this->_store) || !$this->weeeData->isTaxable($this->_store)) {
+            return $this;
+        }
+
+        $items = $this->_getAddressItems($address);
+        if (!count($items)) {
+            return $this;
+        }
+
+        $weeeCodeToItemMap = $address->getWeeeCodeToItemMap();
+        $extraTaxableDetails = $address->getExtraTaxableDetails();
+
+        if (isset($extraTaxableDetails[self::ITEM_TYPE])) {
+            foreach ($extraTaxableDetails[self::ITEM_TYPE] as $itemCode => $weeeAttributesTaxDetails) {
+                $weeeCode = $weeeAttributesTaxDetails[0]['code'];
+                $item = $weeeCodeToItemMap[$weeeCode];
+                $this->weeeData->setApplied($item, []);
+
+                $productTaxes = [];
+
+                $totalValueInclTax = 0;
+                $baseTotalValueInclTax = 0;
+                $totalRowValueInclTax = 0;
+                $baseTotalRowValueInclTax = 0;
+
+                $totalValueExclTax = 0;
+                $baseTotalValueExclTax = 0;
+                $totalRowValueExclTax = 0;
+                $baseTotalRowValueExclTax = 0;
+
+                //Process each weee attribute of an item
+                foreach ($weeeAttributesTaxDetails as $weeeTaxDetails) {
+                    $weeeCode = $weeeTaxDetails[self::KEY_TAX_DETAILS_CODE];
+                    $attributeCode = explode('-', $weeeCode)[1];
+
+                    $valueExclTax = $weeeTaxDetails[self::KEY_TAX_DETAILS_PRICE_EXCL_TAX];
+                    $baseValueExclTax = $weeeTaxDetails[self::KEY_TAX_DETAILS_BASE_PRICE_EXCL_TAX];
+                    $valueInclTax = $weeeTaxDetails[self::KEY_TAX_DETAILS_PRICE_INCL_TAX];
+                    $baseValueInclTax = $weeeTaxDetails[self::KEY_TAX_DETAILS_BASE_PRICE_INCL_TAX];
+
+                    $rowValueExclTax = $weeeTaxDetails[self::KEY_TAX_DETAILS_ROW_TOTAL];
+                    $baseRowValueExclTax = $weeeTaxDetails[self::KEY_TAX_DETAILS_BASE_ROW_TOTAL];
+                    $rowValueInclTax = $weeeTaxDetails[self::KEY_TAX_DETAILS_ROW_TOTAL_INCL_TAX];
+                    $baseRowValueInclTax = $weeeTaxDetails[self::KEY_TAX_DETAILS_BASE_ROW_TOTAL_INCL_TAX];
+
+                    $totalValueInclTax += $valueInclTax;
+                    $baseTotalValueInclTax += $baseValueInclTax;
+                    $totalRowValueInclTax += $rowValueInclTax;
+                    $baseTotalRowValueInclTax += $baseRowValueInclTax;
+
+
+                    $totalValueExclTax += $valueExclTax;
+                    $baseTotalValueExclTax += $baseValueExclTax;
+                    $totalRowValueExclTax += $rowValueExclTax;
+                    $baseTotalRowValueExclTax += $baseRowValueExclTax;
+
+                    $productTaxes[] = array(
+                        'title' => $attributeCode, //TODO: fix this
+                        'base_amount' => $baseValueExclTax,
+                        'amount' => $valueExclTax,
+                        'row_amount' => $rowValueExclTax,
+                        'base_row_amount' => $baseRowValueExclTax,
+                        'base_amount_incl_tax' => $baseValueInclTax,
+                        'amount_incl_tax' => $valueInclTax,
+                        'row_amount_incl_tax' => $rowValueInclTax,
+                        'base_row_amount_incl_tax' => $baseRowValueInclTax,
+                    );
+
+                }
+                $item->setWeeeTaxAppliedAmount($totalValueExclTax)
+                    ->setBaseWeeeTaxAppliedAmount($baseTotalValueExclTax)
+                    ->setWeeeTaxAppliedRowAmount($totalRowValueExclTax)
+                    ->setBaseWeeeTaxAppliedRowAmnt($baseTotalRowValueExclTax);
+
+                $item->setWeeeTaxAppliedAmountInclTax($totalValueInclTax)
+                    ->setBaseWeeeTaxAppliedAmountInclTax($baseTotalValueInclTax)
+                    ->setWeeeTaxAppliedRowAmountInclTax($totalRowValueInclTax)
+                    ->setBaseWeeeTaxAppliedRowAmntInclTax($baseTotalRowValueInclTax);
+
+                $this->processTotalAmount(
+                    $address,
+                    $totalRowValueExclTax,
+                    $baseTotalRowValueExclTax,
+                    $totalRowValueInclTax,
+                    $baseTotalRowValueInclTax
+                );
+
+                $this->weeeData->setApplied($item, array_merge($this->weeeData->getApplied($item), $productTaxes));
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Process row amount based on FPT total amount configuration setting
+     *
+     * @param   \Magento\Sales\Model\Quote\Address $address
+     * @param   float $rowValueExclTax
+     * @param   float $baseRowValueExclTax
+     * @param   float $rowValueInclTax
+     * @param   float $baseRowValueInclTax
+     * @return  $this
+     */
+    protected function processTotalAmount(
+        $address,
+        $rowValueExclTax,
+        $baseRowValueExclTax,
+        $rowValueInclTax,
+        $baseRowValueInclTax
+    ) {
+        if ($this->weeeData->includeInSubtotal($this->_store)) {
+            $address->addTotalAmount('subtotal', $rowValueExclTax);
+            $address->addBaseTotalAmount('subtotal', $baseRowValueExclTax);
+        } else {
+            $address->addTotalAmount('weee', $rowValueExclTax);
+            $address->addBaseTotalAmount('weee', $baseRowValueExclTax);
+        }
+
+        $address->setSubtotalInclTax($address->getSubtotalInclTax() + $rowValueInclTax);
+        $address->setBaseSubtotalInclTax($address->getBaseSubtotalInclTax() + $baseRowValueInclTax);
+        return $this;
+    }
+
+    /**
+     * Fetch the Weee total amount for display in totals block when building the initial quote
+     *
+     * @param   \Magento\Sales\Model\Quote\Address $address
+     * @return  $this
+     */
+    public function fetch(\Magento\Sales\Model\Quote\Address $address)
+    {
+        /** @var $items \Magento\Sales\Model\Order\Item[] */
+        $items = $this->_getAddressItems($address);
+        $store = $address->getQuote()->getStore();
+
+        $weeeTotal = $this->weeeData->getTotalAmounts($items, $store);
+        if ($weeeTotal) {
+            $address->addTotal(
+                array(
+                    'code' => $this->getCode(),
+                    'title' => __('FPT'),
+                    'value' => $weeeTotal,
+                    'area' => null
+                )
+            );
+        }
+        return $this;
+    }
+}
diff --git a/app/code/Magento/Weee/etc/sales.xml b/app/code/Magento/Weee/etc/sales.xml
index fd8aa161ea110737fe406b0436cff1e023d410ca..9899527fa3c63797dde550b709f70c43e2405bbc 100644
--- a/app/code/Magento/Weee/etc/sales.xml
+++ b/app/code/Magento/Weee/etc/sales.xml
@@ -27,6 +27,7 @@
     <section name="quote">
         <group name="totals">
             <item name="weee" instance="Magento\Weee\Model\Total\Quote\Weee" sort_order="225"/>
+            <item name="weee_tax" instance="Magento\Weee\Model\Total\Quote\WeeeTax" sort_order="460"/>
         </group>
         <group name="nominal_totals">
             <item name="nominal_weee" instance="Magento\Weee\Model\Total\Quote\Nominal\Weee" sort_order="600"/>
diff --git a/app/code/Magento/Wishlist/view/frontend/templates/item/list.phtml b/app/code/Magento/Wishlist/view/frontend/templates/item/list.phtml
index acd2b410731a8e1829ed5174957777b5761535c8..da4421f4f50f9e1dd8e1c2938377749a724fa82f 100644
--- a/app/code/Magento/Wishlist/view/frontend/templates/item/list.phtml
+++ b/app/code/Magento/Wishlist/view/frontend/templates/item/list.phtml
@@ -26,7 +26,7 @@
 /** @var \Magento\Wishlist\Block\Customer\Wishlist\Items $this */
 $columns = $this->getColumns();
 ?>
-<div class="wishlist table wrapper">
+<div class="wishlist table-wrapper">
     <table class="table data wishlist" id="wishlist-table">
         <caption class="table caption"><?php echo __('Wish List') ?></caption>
         <thead>
diff --git a/app/code/Magento/Wishlist/view/frontend/templates/shared.phtml b/app/code/Magento/Wishlist/view/frontend/templates/shared.phtml
index c540f0b04407c6a318015a89dc20a799ed831d12..6620bdcab6a9bdbc54e7c464722c7ae05fcb71a7 100644
--- a/app/code/Magento/Wishlist/view/frontend/templates/shared.phtml
+++ b/app/code/Magento/Wishlist/view/frontend/templates/shared.phtml
@@ -27,7 +27,7 @@ $imageBlock =  $this->getLayout()->createBlock('Magento\Catalog\Block\Product\Im
 
 <?php if ($this->hasWishlistItems()): ?>
     <form class="form shared wishlist" action="<?php echo $this->getUrl('*/*/update') ?>" method="post">
-        <div class="wishlist table wrapper">
+        <div class="wishlist table-wrapper">
             <table class="table data wishlist" id="wishlist-table">
                 <thead>
                 <tr>
diff --git a/app/design/frontend/Magento/blank/Magento_Bundle/web/css/source/module.less b/app/design/frontend/Magento/blank/Magento_Bundle/web/css/source/module.less
index 3d5f3b03652dfde650dbc8dadbd4dcdaa72bcbe8..2e7073e03aeaca530783c764d991343cb01dfda1 100644
--- a/app/design/frontend/Magento/blank/Magento_Bundle/web/css/source/module.less
+++ b/app/design/frontend/Magento/blank/Magento_Bundle/web/css/source/module.less
@@ -42,7 +42,7 @@
     }
 
     .input-text.qty {
-        &:extend(.input-qty all);
+        &:extend(.abstract-input-qty all);
     }
 
     .product-options-wrapper {
diff --git a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/module.less b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/module.less
index f527eb55d116a648c08f1a59aa8db38bdf33294c..8dd6f5343de2204ca1b0e6b31a93fa7694899747 100644
--- a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/module.less
+++ b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/module.less
@@ -472,7 +472,7 @@
     .action.tocompare {
         &:extend(.abstract-action-addto all);
     }
-    .product.reviews.summary .reviews.actions {
+    .product-reviews-summary .reviews-actions {
         .font-size(@font-size-base);
     }
 }
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/cart.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/cart.less
index 8d79a752015f3a3fd10078e9c1dd47cca219ceb0..a3dbfa007515fcdbb09bddbf0168c35680052e33 100644
--- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/cart.less
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/cart.less
@@ -48,14 +48,14 @@
                 cursor: pointer;
                 display: block;
                 font-weight: @font-weight-semibold;
-                line-height: 36px;
                 margin-bottom: 0;
-                padding: 0 20px 0 5px;
+                overflow: hidden;
+                padding: 7px 20px 7px 5px;
                 position: relative;
                 &:after {
                     position: absolute;
                     right: 0;
-                    top: 0;
+                    top: -5px;
                 }
                 strong {
                     .column.main & {
@@ -64,18 +64,21 @@
                     }
                 }
             }
+            > .content {
+                display: none;
+            }
             &.active {
-                .content {
-                    display: block;
-                }
                 > .title {
                     .icon-font-symbol(
                         @_icon-font-content: @icon-prev,
                         @_icon-font-position: after
                     );
                 }
+                > .content {
+                    display: block;
+                }
             }
-            .item.options {
+            .item-options {
                 margin-left: 0;
             }
             .fieldset {
@@ -108,67 +111,97 @@
             padding-right: 4px;
             text-align: right;
         }
-        .grand .mark,
-        .grand .amount {
-            padding-top: 25px;
-        }
-        .grand .mark strong {
-            font-weight: @font-weight-base;
+        .grand {
+            .mark,
+            .amount {
+                padding-top: 25px;
+            }
+            .mark strong {
+                font-weight: @font-weight-base;
+            }
         }
         .msrp {
             margin-bottom: @indent-s-base;
         }
-    }
-
-    //  Products table
-    &.table.wrapper {
-        thead {
-            .col.price,
-            .col.subtotal {
-                display: none;
-            }
-        }
-        .cart.items {
-            .action {
-                &:extend(button all);
-                .link-as-button();
-                margin-left: 10px;
-                &:first-child {
-                    margin-left: 0;
+        .totals-tax {
+            &-summary {
+                .mark,
+                .amount {
+                    border-top: @border-width-base solid @border-color-base;
+                    border-bottom: @border-width-base solid @border-color-base;
+                    cursor: pointer;
                 }
-                &.help.map {
-                    &:extend(.abstract-action-button-as-link all);
-                    font-weight: @font-weight-base;
+                .amount .price {
+                    position: relative;
+                    padding-right: 25px;
+                    .icon-font(
+                        @icon-down,
+                        @_icon-font-size: 30px,
+                        @_icon-font-text-hide: true,
+                        @_icon-font-position: after,
+                        @_icon-font-display: block
+                    );
+                    &:after {
+                        position: absolute;
+                        right: -5px;
+                        top: -12px;
+                    }
+                }
+                &.expanded {
+                    .mark,
+                    .amount {
+                        border-bottom: 0;
+                    }
+                    .amount .price {
+                        .icon-font-symbol(
+                            @_icon-font-content: @icon-up,
+                            @_icon-font-position: after
+                        );
+                    }
                 }
             }
-            thead + .cart.item {
+            &-details {
+                display: none;
+                border-bottom: @border-width-base solid @border-color-base;
+                &.shown {
+                    display: table-row;
+                }
+            }
+        }
+    }
+
+    //  Products table
+    &.table-wrapper {
+        .items {
+            thead + .item {
                 border-top: @border-width-base solid @border-color-base;
             }
-            > .item.cart {
+            > .item {
                 border-bottom: @border-width-base solid @border-color-base;
-                display: block;
                 position: relative;
             }
         }
-        .col.price,
-        .col.subtotal {
-            display: block;
-            text-align: left;
-            white-space: nowrap;
-            &:before {
-                content: attr(data-th) ":";
-                color: @color-primary-lighter;
-                display: inline-block;
-                font-size: @font-size-s;
-                padding-left: 5px;
+        .col {
+            &.qty,
+            &.price,
+            &.subtotal,
+            &.msrp {
+                padding-top: 20px;
+                &:extend(.abstract-incl-excl-tax all);
+            }
+            &.qty {
+                .input-text {
+                    margin-top: -3px;
+                    width: 45px;
+                }
             }
-        }
-        .col.qty {
-            right: 0;
-            position: absolute;
-            width: 45px;
         }
         .item {
+            &-actions td {
+                padding-bottom: 20px;
+                text-align: center;
+                white-space: normal;
+            }
             .col {
                 &.item {
                     display: block;
@@ -177,19 +210,26 @@
                     min-height: 75px;
                 }
                 &.qty {
-                    top: 0;
-                    padding-top: 20px;
                     .input-text {
-                        &:extend(.input-qty all);
+                        &:extend(.abstract-input-qty all);
                     }
                 }
             }
-            &.actions td {
-                padding-bottom: 20px;
+        }
+        .action {
+            &:extend(button all);
+            .link-as-button();
+            margin-left: 10px;
+            &:first-child {
+                margin-left: 0;
+            }
+            &.help.map {
+                &:extend(.abstract-action-button-as-link all);
+                font-weight: @font-weight-base;
             }
         }
         .product {
-            &.photo {
+            &-item-photo {
                 display: block;
                 max-width: 60px;
                 left: 0;
@@ -198,23 +238,31 @@
                 top: 15px;
                 width: 100%;
             }
-            &.details {
+            &-item-details {
                 display: table-cell;
                 vertical-align: top;
+                white-space: normal;
                 width: 99%;
-                .product.name {
-                    font-weight: @font-weight-base;
-                }
+            }
+            &-item-name {
+                display: inline-block;
+                font-weight: @font-weight-base;
+                max-width: 130px;
+                overflow: hidden;
+                text-overflow: ellipsis;
             }
         }
         //  Product options
-        .item.options {
+        .cart-item-options {
             font-size: @font-size-s;
             margin-top: @indent-s-base;
             margin-bottom: @indent-s-base;
             &:extend(.product-options-list all);
             &:extend(.add-clearfix all);
         }
+        .cart-tax-total {
+            &:extend(.abstract-tax-total all);
+        }
     }
     &-container {
         .form.cart {
@@ -255,7 +303,7 @@
                 }
             }
         }
-        .checkout.methods {
+        .checkout-methods-items {
             &:extend(.reset-list all);
             text-align: center;
             margin-top: @indent-s-base;
@@ -271,11 +319,55 @@
 //
 //    Cross sell
 //--------------------------------------
-
 .block.crosssell {
     margin-top: 70px;
 }
 
+//
+//    Mobile
+//--------------------------------------
+.responsive-smaller(@break) when (@break = @break-point-1) {
+    .cart {
+        &.table-wrapper {
+            thead {
+                .col {
+                    &.price,
+                    &.qty,
+                    &.subtotal,
+                    &.msrp {
+                        display: none;
+                    }
+                }
+            }
+            .col {
+                &.qty,
+                &.price,
+                &.subtotal,
+                &.msrp {
+                    .box-sizing();
+                    display: block;
+                    float: left;
+                    text-align: center;
+                    white-space: nowrap;
+                    width: 33%;
+                    &:before {
+                        content: attr(data-th) ":";
+                        display: block;
+                        font-weight: @font-weight-bold;
+                        padding-bottom: 10px;
+                    }
+                }
+                &.msrp {
+                    white-space: normal;
+                }
+            }
+            .item .col.item {
+                padding-bottom: 0;
+            }
+        }
+    }
+}
+
 //
 //    Desktop
 //--------------------------------------
@@ -287,11 +379,10 @@
                 float: left;
                 width: 73%;
                 position: relative;
-                .actions.main {
+                .actions {
                     text-align: left;
                 }
                 .action {
-                    margin-bottom: 0;
                     &.continue {
                         float: left;
                     }
@@ -314,7 +405,7 @@
             width: 23%;
             .actions-toolbar {
                 .column.main & {
-                    margin-left: 0;
+                    &:extend(.reset-left-margin-desktop all);
                     > .secondary {
                         float: none;
                     }
@@ -330,40 +421,18 @@
             }
         }
 
-        &.table.wrapper {
-            thead {
-                .col.price,
-                .col.subtotal {
-                    display: table-cell;
-                }
-            }
-            .cart.items > .item.cart {
-                display: table-row-group;
-            }
-            .col {
-                &.price,
-                &.subtotal {
-                    display: table-cell;
-                    text-align: center;
-                    padding-top: 27px;
-                    &:before {
-                        display: none;
-                    }
-                }
-                &.qty {
-                    position: static;
-                }
-            }
-
+        &.table-wrapper {
             .item {
-                .col.item {
-                    padding: 27px 8px 10px;
+                .col {
+                    &.item {
+                        padding: 27px 8px 10px;
+                    }
                 }
                 &.actions td {
                     text-align: right;
                 }
             }
-            .product.photo {
+            .product-item-photo {
                 display: table-cell;
                 padding-right: 20px;
                 vertical-align: top;
diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module.less
index 6b321311f259c44744aed639ab846adb28a9cfdc..dde2b9b948bdf6a9e6e778e41b83768af104108e 100644
--- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module.less
+++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module.less
@@ -149,6 +149,7 @@
         th.col.subtotal {
             text-align: center;
         }
+        .mark,
         .amount {
             text-align: right;
         }
@@ -217,7 +218,7 @@
             overflow: hidden;
         }
         .action,
-        .payment.method .title {
+        .payment-method .title {
             font-weight: @font-weight-base;
         }
         .data.table {
diff --git a/app/design/frontend/Magento/blank/Magento_Customer/web/css/source/module.less b/app/design/frontend/Magento/blank/Magento_Customer/web/css/source/module.less
index c7a50d4a76cda76d9057a9760d959fc3fec38aeb..1455462bd7c7123457b9e4cb7dcea15c6cc510c0 100644
--- a/app/design/frontend/Magento/blank/Magento_Customer/web/css/source/module.less
+++ b/app/design/frontend/Magento/blank/Magento_Customer/web/css/source/module.less
@@ -22,6 +22,13 @@
 //  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 //  */
 
+@account-nav-background: #e8e8e8;
+@account-nav-color: false;
+@account-nav-current-color: false;
+@account-nav-current-font-weight: @font-weight-base;
+@account-nav-current-border: 3px solid transparent;
+@account-nav-current-border-color: #ff5501;
+
 .login.container {
     .block {
         &.new {
@@ -42,7 +49,7 @@
     }
 }
 
-.block.addresses.list {
+.block-addresses-list {
     .items.addresses {
         > .item {
             margin-bottom: @indent-base;
@@ -53,24 +60,23 @@
     }
 }
 
-.address.edit {
+.form-address-edit {
     #region_id {
-		display: none;
-	}
+        display: none;
+    }
 }
 
-.form.edit.account{
-    .fieldset.password{
+.form-edit-account {
+    .fieldset.password {
         display: none;
-	}
+    }
 }
 
-.address.billing,
-.address.shipping,
-.box.information,
-.box.newsletter {
-    address,
-    p {
+.box-address-billing,
+.box-address-shipping,
+.box-information,
+.box-newsletter {
+    .box-content {
         line-height: 26px;
     }
 }
@@ -85,12 +91,14 @@
         h2 {
             margin-top: 0;
         }
-        .products.toolbar {
-            background: transparent;
-            margin-bottom: @indent-base;
+        .toolbar {
+            text-align: center;
+            .limiter-options {
+                width: auto;
+            }
         }
         .block:not(.widget) {
-            .title {
+            .block-title {
                 > strong {
                     .heading(h3);
                 }
@@ -99,7 +107,7 @@
                     margin-left: 15px;
                 }
             }
-            .subtitle {
+            .box-title {
                 > span {
                     .heading(h4);
                 }
@@ -110,7 +118,7 @@
                     margin-left: 15px;
                 }
             }
-            .content {
+            .block-content {
                 p:last-child {
                     margin-bottom: 0;
                 }
@@ -120,8 +128,8 @@
             }
         }
     }
-    .block.account.nav {
-        background: @sidebar-background;
+    .block.account-nav {
+        .css(background, @sidebar-background);
         padding: 15px 0;
         .title {
             padding: 0 18px;
@@ -146,32 +154,29 @@
                     border-left: 3px solid transparent;
                 }
                 a {
+                    .css(color, @account-nav-color);
                     text-decoration: none;
                     &:hover {
-                        background: #e8e8e8;
+                        .css(background, @account-nav-background);
                     }
                 }
                 &.current {
                     strong {
-                        border-color: #ff5501;
+                        .css(color, @account-nav-current-color);
+                        .css(border-color, @account-nav-current-border-color);
                         font-weight: normal;
                     }
                 }
             }
         }
     }
-
-    .wrapper.table {
+    .table-wrapper {
         margin-bottom: @indent-base;
         &:last-child {
             margin-bottom: 0;
         }
         .data.table {
-            .table-bordered(
-                @_type: light,
-                @_border-width: 1px
-            );
-            margin-bottom: 0;
+            .table-striped(@_stripped-highlight: even);
             .col.actions {
                 .action {
                     margin-right: 15px;
@@ -180,7 +185,7 @@
                     }
                 }
             }
-        }
+        } 
     }
 }
 
@@ -201,6 +206,12 @@
         }
         margin-bottom: @indent-s-base;
     }
+    p:last-child {
+        margin: 0;
+    }
+    .box-actions {
+        margin-top: @indent-xs-base;
+    }
 }
 
 
@@ -269,7 +280,7 @@
     .account {
         .column.main {
             .block:not(.widget) {
-                .content {
+                .block-content {
                     &:extend(.add-clearfix-desktop all);
                     .box {
                         &:extend(.blocks-2columns all);
@@ -277,9 +288,38 @@
                 }
             }
         }
+        .data.table {
+            .table-bordered(
+                @_type: light,
+                @_border-width: 1px
+            );
+            margin-bottom: 0;
+        }
+        .toolbar {
+            position: relative;
+            margin-bottom: @indent-base;
+            &:extend(.add-clearfix-desktop all);
+            .limiter {
+                float: right;
+                position: relative;
+                z-index: 1;
+            }
+            .toolbar-amount {
+                float: left;
+                line-height: normal;
+                padding: 7px 0 0;
+                position: relative;
+                z-index: 1;
+            }
+            .pages {
+                position: absolute;
+                z-index: 0;
+                width: 100%;
+            }
+        }
     }
 
-    .block.addresses.list {
+    .block-addresses-list {
         .items.addresses {
             &:extend(.add-clearfix-desktop all);
             > .item {
@@ -297,3 +337,28 @@
         clear: both;
     }
 }
+
+//
+//    Mobile
+//--------------------------------------
+.responsive-smaller(@break) when (@break = @break-point-0) {
+    .account {
+        .data.table {
+            &:extend(.table-vertical-mobile all);
+            .col.actions {
+                padding-top: 9px;
+                padding-bottom: 15px;
+                &:before {
+                    &:extend(.visually-hidden-mobile all);
+                }
+            }
+        }
+        .toolbar {
+            .toolbar-amount,
+            .limiter,
+            .pages {
+                margin-bottom: 25px;
+            }
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Downloadable/web/css/source/module.less b/app/design/frontend/Magento/blank/Magento_Downloadable/web/css/source/module.less
index fd1768f6b28443e209f7ed00f9bd5e04c1f0969e..056e7779ae48df6dca62cc5bcd56e59c1ab58bc2 100644
--- a/app/design/frontend/Magento/blank/Magento_Downloadable/web/css/source/module.less
+++ b/app/design/frontend/Magento/blank/Magento_Downloadable/web/css/source/module.less
@@ -28,3 +28,8 @@
         margin: 0 0 @indent-s-base;
     }
 }
+.table-downloadable-products {
+    .product-name {
+        margin-right: 15px;
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Paypal/web/css/source/module.less b/app/design/frontend/Magento/blank/Magento_Paypal/web/css/source/module.less
index 31afa08f51c7ecdfbd0d030a7629c9f937265696..a577bbb64431080640b30620df57fd670fd1e200 100644
--- a/app/design/frontend/Magento/blank/Magento_Paypal/web/css/source/module.less
+++ b/app/design/frontend/Magento/blank/Magento_Paypal/web/css/source/module.less
@@ -42,7 +42,7 @@
     }
 }
 
-.form.new.agreement {
+.form-new-agreement {
     .actions-toolbar {
         &:extend(.reset-left-margin all);
     }
diff --git a/app/design/frontend/Magento/blank/Magento_Review/web/css/source/module.less b/app/design/frontend/Magento/blank/Magento_Review/web/css/source/module.less
index 8b07a3b0fc104f0f84b8e11ebefea077b27d5cf8..694752b2b22b64ebb6e7088fe9af6030336a5fb2 100644
--- a/app/design/frontend/Magento/blank/Magento_Review/web/css/source/module.less
+++ b/app/design/frontend/Magento/blank/Magento_Review/web/css/source/module.less
@@ -22,6 +22,25 @@
 //  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 //  */
 
+
+.rating-summary {
+    .mixin-rating-summary();
+    .rating-result {
+        margin-left: -5px;
+    }
+}
+
+.product-reviews-summary,
+.table-reviews {
+    .rating-summary {
+        .mixin-rating-summary-label-hide();
+    }
+}
+
+.review-control-vote {
+    .mixin-rating-vote();
+}
+
 //
 //    Add reviewblock
 //--------------------------------------
@@ -64,7 +83,7 @@
 }
 
 .data.table.reviews {
-    .rating.summary {
+    .rating-summary {
         margin-top: -4px;
     }
 }
@@ -77,7 +96,7 @@
     }
 }
 
-.product.reviews.summary {
+.product-reviews-summary {
     display: table;
     .products.wrapper.list & {
         margin: 0 auto;
@@ -85,14 +104,14 @@
     &.empty {
         margin-left: 0;
     }
-    .rating.summary {
+    .rating-summary {
         position: relative;
         left: -@indent-xs-base;
         display: table-cell;
         vertical-align: middle;
         text-align: left;
     }
-    .reviews.actions {
+    .reviews-actions {
         display: table-cell;
         vertical-align: middle;
         line-height: floor(@rating-icon-font-size * @line-height-base);
@@ -109,9 +128,55 @@
 //    Desktop
 //--------------------------------------
 .responsive(@break) when (@break = @break-point-1) {
-    .product.reviews.summary {
+    .product-reviews-summary {
         .products.wrapper.list & {
             margin: 0;
         }
     }
 }
+
+.customer-review {
+    .product-details {
+        &:extend(.add-clearfix all);
+        margin-bottom: @indent-xl-base;
+        .rating-average-label {
+        }
+    }
+    .product-media {
+        width: 30%;
+        max-width: 285px;
+        float: left;
+        margin-right: 3%;
+    }
+    .product-info {
+    }
+    .review-details {
+        .title {
+        }
+        .customer-review-rating {
+            .css(margin-bottom, @indent-base);
+            .item {
+                .css(margin-bottom, @indent-s-base);
+                &:last-child {
+                    margin-bottom: 0;
+                }
+            }
+        }
+        .review-title {
+            .heading(h3);
+            .css(font-weight, @font-weight-semibold);
+            .css(margin-bottom, @indent-base);
+        }
+        .review-content {
+            .css(margin-bottom, @indent-base);
+        }
+        .review-date {
+        }
+    }
+    .product-reviews-summary {
+        .rating-summary,
+        .reviews-actions {
+            display: block;
+        }
+    }
+}
diff --git a/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/module.less b/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/module.less
index b6e4b22ad5d5ef09bcaa9c43d0ff31201e38c5bb..dd693905d1179710eb5ac9c81b8a9d23ad48ddd9 100644
--- a/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/module.less
+++ b/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/module.less
@@ -22,43 +22,81 @@
 //  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 //  */
 
-.order.details {
-    ul.items {
-        &:extend(.reset-list all);
-        margin-bottom: @indent-base;
-        .label:after {
-            content: ": ";
+.order-links {
+    border-bottom: @border-width-base solid @border-color-base;
+    margin-bottom: 10px;
+    .item {
+        display: inline-block;
+        margin-right: 20px;
+    }
+}
+
+.order-actions-toolbar {
+    .action {
+        margin: 0 20px 0 0;
+    }
+}
+
+.order-details-items {
+    border-bottom: @border-width-base solid @border-color-base;
+    margin-bottom: 20px;
+    padding-bottom: 10px;
+    .order-title {
+        > strong {
+            .heading(h3);
+            display: inline-block;
         }
-        strong {
-            font-weight: normal;
+    }
+    .col {
+        &.price,
+        &.subtotal {
+            &:extend(.abstract-incl-excl-tax all);
         }
     }
-    .order.status {
-        display: inline-block;
-        .heading(h2);
-        margin-top: 0;
-    }
-    .order.date {
-        margin-bottom: @indent-base;
-    }
-    .order.toolbar {
-        float: right;
-        .action {
-            margin-left: 15px;
-            &:first-child {
-                margin-left: 0;
+    .cart-tax-total {
+        &:extend(.abstract-tax-total all);
+    }
+    .items-qty {
+        &:extend(.reset-list all);
+        .item {
+            white-space: nowrap;
+        }
+        .title {
+            &:after {
+                content: ": ";
             }
         }
     }
-    .order.subtitle.caption,
-    .order.title  {
-        strong {
-            .heading(h3);
+    .table-order-items {
+        .table-bordered(
+            @_type: horizontal
+        );
+        .account & {
+            tfoot {
+                tr:first-child td {
+                    border-top: @table-border-width @table-border-style @table-border-color;
+                }
+            }
         }
-        .action {
-            margin-left: 15px;
+        .item.options {
+            dt {
+                margin: 0;
+            }
+            dd {
+                margin: 0 0 15px;
+            }
+            &.links {
+                dt {
+                    display: inline-block;
+                    &:after {
+                        content: ": ";
+                    }
+                }
+                dd {
+                    margin: 0;
+                }
+            }
         }
-        margin-bottom: @indent-base;
     }
 }
 
@@ -89,14 +127,93 @@
     }
 }
 
+.block-order-details {
+    &-comments {
+        margin: 0 0 40px;
+        .comment-date {
+            font-weight: @font-weight-semibold;
+        }
+        .comment-content {
+            line-height: 1.6;
+            margin: 0 0 20px;
+        }
+    }
+
+    &-view {
+        .box-content {
+            .payment-method {
+                .title {
+                    font-weight: @font-weight-base;
+                }
+                .content {
+                    margin: 0;
+                    > strong {
+                        font-weight: @font-weight-base;
+                        &:after {
+                            content: ': ';
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+.order-tracking {
+    border-bottom: @border-width-base solid @border-color-base;
+    margin: 0;
+    padding: 20px 0;
+    .tracking-title {
+        display: inline-block;
+    }
+    .tracking-content {
+        display: inline-block;
+        margin: 0 0 0 5px;
+    }
+}
+
 //
 //    Desktop
 //--------------------------------------
 .responsive(@break) when (@break = @break-point-1) {
-    .order.details {
-        &:extend(.add-clearfix-desktop all);
-        .block {
-            &:extend(.blocks-2columns all);
+    .account {
+        .page-title {
+            .order-actions-toolbar {
+                margin: -20px 0 0;
+                text-align: right;
+                .action {
+                    margin: 0 0 0 20px;
+                }
+            }
+        }
+        .table-order-items {
+            .col {
+                &.subtotal {
+                    text-align: right;
+                }
+            }
+            .mark,
+            .amount {
+                text-align: right;
+            }
+        }
+    }
+}
+
+//
+//    Mobile
+//--------------------------------------
+.responsive-smaller(@break) when (@break = @break-point-0) {
+    .account {
+        .order-details-items {
+            .table-order-items {
+                tbody,
+                tfoot {
+                    > tr > td {
+                        border: none;
+                    }
+                }
+            }
         }
     }
 }
diff --git a/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/module.less b/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/module.less
index de10fd08903f8818517bc0a948f031a6e78d48e9..fa04146e02100fe5013acb036d633092d5ac76d5 100644
--- a/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/module.less
+++ b/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/module.less
@@ -35,7 +35,7 @@
     }
 }
 
-.account .table.wrapper .data.table.wishlist {
+.account .table-wrapper .data.table.wishlist {
     .table-bordered(@_type: horizontal);
     thead > tr > th {
         border-bottom: 0;
@@ -51,7 +51,7 @@
         margin: @indent-s-base 0;
         .qty {
             vertical-align: middle;
-            &:extend(.input-qty all);
+            &:extend(.abstract-input-qty all);
         }
     }
     .col {
diff --git a/app/design/frontend/Magento/blank/web/css/source/abstract.less b/app/design/frontend/Magento/blank/web/css/source/abstract.less
index 3bde20e922e2ba0b2deb708fdaa3ad1aa2436900..38fc00f5edd91e08955d7dc15260f224a9fa3c6c 100644
--- a/app/design/frontend/Magento/blank/web/css/source/abstract.less
+++ b/app/design/frontend/Magento/blank/web/css/source/abstract.less
@@ -32,21 +32,17 @@
     }
 }
 
-//
-//    Primary button
-//--------------------------------------
-.action-primary {
-    .button-primary();
-    border-radius: @button-border-radius;
-}
-
 //
 //    Link as a button
 //--------------------------------------
 .action-link-button {
-  .button();
-  .link-as-button();
-  border-radius: @button-border-radius;
+    .button();
+    .link-as-button();
+    border-radius: @button-border-radius;
+    &:active,
+    &:focus {
+        box-shadow: none;
+    }
 }
 
 //
@@ -123,7 +119,7 @@
 //
 //    Input quantity
 //--------------------------------------
-.input-qty {
+.abstract-input-qty {
     .form-element-size(@_width: 47px);
     text-align: center;
 }
@@ -275,6 +271,12 @@
     .visually-hidden();
 }
 
+.responsive-smaller(@break) when (@break = @break-point-0) {
+    .visually-hidden-mobile {
+        .visually-hidden();
+    } 
+}
+
 //
 //    Clearfix
 //--------------------------------------
@@ -288,6 +290,12 @@
     }
 }
 
+.responsive-smaller(@break) when (@break = @break-point-0) {
+    .add-clearfix-mobile {
+        .clearfix();
+    }
+}
+
 //
 //    Box-sizing
 //--------------------------------------
@@ -393,3 +401,77 @@
 .abstract-box-tocart {
     margin: @indent-s-base 0;
 }
+
+//
+//    Vertical Table
+//--------------------------------------
+.responsive-smaller(@break) when (@break = @break-point-0) {
+    .table-vertical-mobile {
+        .table-responsive();
+        tbody > tr {
+            > td {
+                padding-left: 0;
+                padding-right: 0;
+            }
+            &:not(:last-child) {
+                td:last-child {
+                    padding-bottom: @indent-base;
+                }
+            }
+        }
+    }
+}
+
+//
+//    Excl/Incl tax
+//--------------------------------------
+.abstract-incl-excl-tax {
+    .tax {
+        display: block;
+        .font-size(18);
+        line-height: 1;
+        .price {
+            font-weight: @font-weight-bold;
+        }
+    }
+
+    .incl.tax + .excl.tax,
+    .weee {
+        display: block;
+        .font-size(18);
+        &:before {
+            content: attr(data-th) ": ";
+            .font-size(11);
+        }
+        .price {
+            .font-size(11);
+        }
+    }
+}
+
+//
+//    Cart tax total
+//--------------------------------------
+.abstract-tax-total {
+    cursor: pointer;
+    position: relative;
+    padding-right: 12px;
+    .icon-font(
+        @icon-down,
+        @_icon-font-size: 26px,
+        @_icon-font-line-height: 10px,
+        @_icon-font-margin: 3px 0 0 0,
+        @_icon-font-position: after
+    );
+    &:after {
+        position: absolute;
+        right: -7px;
+        top: 3px;
+    }
+    &-expanded {
+        .icon-font-symbol(
+            @_icon-font-content: @icon-up,
+            @_icon-font-position: after
+        );
+    }
+}
diff --git a/app/design/frontend/Magento/blank/web/css/source/buttons.less b/app/design/frontend/Magento/blank/web/css/source/buttons.less
index ff95002797404c48426176a42172917c8a07cb50..bb9acced2ccda34aa213f697f6144575f9938965 100644
--- a/app/design/frontend/Magento/blank/web/css/source/buttons.less
+++ b/app/design/frontend/Magento/blank/web/css/source/buttons.less
@@ -24,7 +24,7 @@
 
 //
 //    Using buttons mixins
-//-------------------------------------- */
+//--------------------------------------
 button {
     border-radius: @button-border-radius;
     &:active,
diff --git a/app/design/frontend/Magento/blank/web/css/source/forms.less b/app/design/frontend/Magento/blank/web/css/source/forms.less
index 1e8a6def1b96b98b570756222e3c3665e97024b1..9b9f437b208766d3dbb4fee34aed33ebeb89feec 100644
--- a/app/design/frontend/Magento/blank/web/css/source/forms.less
+++ b/app/design/frontend/Magento/blank/web/css/source/forms.less
@@ -46,6 +46,7 @@
         &.choice {
             .label {
                 font-weight: normal;
+                display: inline;
             }
         }
         .label {
diff --git a/app/design/frontend/Magento/blank/web/css/source/rating.less b/app/design/frontend/Magento/blank/web/css/source/rating.less
index 64c7c814bd75c3093cf83bd181224e9526ec3934..44d20b26e20c523599adc0ed9892488722eaa5d5 100644
--- a/app/design/frontend/Magento/blank/web/css/source/rating.less
+++ b/app/design/frontend/Magento/blank/web/css/source/rating.less
@@ -23,20 +23,8 @@
 //  */
 
 // .block.reviews.dashboard,
-// .product.reviews.summary,
+// .product-reviews-summary,
 // .data.table.reviews,
 // .block.reviews.list,
-// .customer.review.view 
+// .customer.review.view
 
-.rating.summary {
-    .rating-summary();
-}
-
-.product.reviews.summary,
-.data.table.reviews {
-    .rating-summary-label-hide();
-}
-
-.control.rating.vote {
-    .rating-vote();
-}
diff --git a/app/design/frontend/Magento/blank/web/css/source/tables.less b/app/design/frontend/Magento/blank/web/css/source/tables.less
index 04a1c24ad5d30a109af272d7caf471199ed8b218..91e66d34923274baf1edeff84822d5e1b3fc146e 100644
--- a/app/design/frontend/Magento/blank/web/css/source/tables.less
+++ b/app/design/frontend/Magento/blank/web/css/source/tables.less
@@ -22,7 +22,7 @@
 //  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 //  */
 
-.wrapper.table {
+.table-wrapper {
     .table-overflow();
     position: relative; // to hide unnecessary horizontal scrollbar in Safari
     > table {
@@ -35,7 +35,7 @@
 //    Desktop
 //--------------------------------------
 .responsive(@break) when (@break = @break-point-1) {
-    .wrapper.table {
+    .table-wrapper {
         overflow-y: visible;
         overflow-x: visible;
         > table {
@@ -45,7 +45,7 @@
                 > tr {
                     > th,
                     > td {
-                        white-space: normal;
+                        //white-space: normal;
                     }
                 }
             }
diff --git a/app/design/frontend/Magento/blank/web/js/theme.js b/app/design/frontend/Magento/blank/web/js/theme.js
index f492c996cc6ea7b298805f5a3abe1651e0f48adf..d23207ae1ca5cd306ebd79275bd316d2e94e0488 100644
--- a/app/design/frontend/Magento/blank/web/js/theme.js
+++ b/app/design/frontend/Magento/blank/web/js/theme.js
@@ -34,6 +34,11 @@
                 });
             }
         }
+        if($('.cart-summary').length){
+            $('.cart-summary').mage('sticky', {
+                container: '.cart-container'
+            });
+        }
     });
 
 })(window.jQuery);
diff --git a/app/i18n/Magento/de_DE/language.xml b/app/i18n/magento/de_de/language.xml
similarity index 95%
rename from app/i18n/Magento/de_DE/language.xml
rename to app/i18n/magento/de_de/language.xml
index 1c019d56b856343140a8963dc9560a1872c20dd0..2aca9717fea826070d3092f17b54e756994f00f3 100644
--- a/app/i18n/Magento/de_DE/language.xml
+++ b/app/i18n/magento/de_de/language.xml
@@ -25,5 +25,6 @@
 -->
 <language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
     <code>de_DE</code>
-    <vendor>Magento</vendor>
+    <vendor>magento</vendor>
+    <package>de_de</package>
 </language>
diff --git a/app/i18n/Magento/en_US/language.xml b/app/i18n/magento/en_us/language.xml
similarity index 95%
rename from app/i18n/Magento/en_US/language.xml
rename to app/i18n/magento/en_us/language.xml
index 4f7b0310a0ad9537c33ff34291c78cc0ecee200c..d7c59ae84e3c6d8301b858c5a526858eb51c00cb 100644
--- a/app/i18n/Magento/en_US/language.xml
+++ b/app/i18n/magento/en_us/language.xml
@@ -25,5 +25,6 @@
 -->
 <language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
     <code>en_US</code>
-    <vendor>Magento</vendor>
+    <vendor>magento</vendor>
+    <package>en_us</package>
 </language>
diff --git a/app/i18n/Magento/es_ES/language.xml b/app/i18n/magento/es_es/language.xml
similarity index 95%
rename from app/i18n/Magento/es_ES/language.xml
rename to app/i18n/magento/es_es/language.xml
index f0466320b88579dcf6b552be17998d6a267e80e6..e2ed071a4614956804831642796c94509bc26f23 100644
--- a/app/i18n/Magento/es_ES/language.xml
+++ b/app/i18n/magento/es_es/language.xml
@@ -25,5 +25,6 @@
 -->
 <language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
     <code>es_ES</code>
-    <vendor>Magento</vendor>
+    <vendor>magento</vendor>
+    <package>es_es</package>
 </language>
diff --git a/app/i18n/Magento/fr_FR/language.xml b/app/i18n/magento/fr_fr/language.xml
similarity index 95%
rename from app/i18n/Magento/fr_FR/language.xml
rename to app/i18n/magento/fr_fr/language.xml
index 461fdf7a05d7767c5545ece3d8450e8be89a9e31..065b5c46706c99fbbc41f5365bd161c7a59c519f 100644
--- a/app/i18n/Magento/fr_FR/language.xml
+++ b/app/i18n/magento/fr_fr/language.xml
@@ -25,5 +25,6 @@
 -->
 <language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
     <code>fr_FR</code>
-    <vendor>Magento</vendor>
+    <vendor>magento</vendor>
+    <package>fr_fr</package>
 </language>
diff --git a/app/i18n/Magento/nl_NL/language.xml b/app/i18n/magento/nl_nl/language.xml
similarity index 95%
rename from app/i18n/Magento/nl_NL/language.xml
rename to app/i18n/magento/nl_nl/language.xml
index 99fbfee22d806945a1e7396f6151df3f321c5f23..a96ef312fb12fec60c0814ea85b0061be636fbfd 100644
--- a/app/i18n/Magento/nl_NL/language.xml
+++ b/app/i18n/magento/nl_nl/language.xml
@@ -25,5 +25,6 @@
 -->
 <language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
     <code>nl_NL</code>
-    <vendor>Magento</vendor>
+    <vendor>magento</vendor>
+    <package>nl_nl</package>
 </language>
diff --git a/app/i18n/Magento/pt_BR/language.xml b/app/i18n/magento/pt_br/language.xml
similarity index 95%
rename from app/i18n/Magento/pt_BR/language.xml
rename to app/i18n/magento/pt_br/language.xml
index 401fc7016a56fc8096d02588f018d264a0311777..6f88d457d0f7669e4ce1afe2885988f98eeec7d9 100644
--- a/app/i18n/Magento/pt_BR/language.xml
+++ b/app/i18n/magento/pt_br/language.xml
@@ -25,5 +25,6 @@
 -->
 <language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
     <code>pt_BR</code>
-    <vendor>Magento</vendor>
+    <vendor>magento</vendor>
+    <package>pt_br</package>
 </language>
diff --git a/app/i18n/Magento/zh_CN/language.xml b/app/i18n/magento/zh_cn/language.xml
similarity index 95%
rename from app/i18n/Magento/zh_CN/language.xml
rename to app/i18n/magento/zh_cn/language.xml
index af174e14d44f1cd44cdcd5f047d6ed83e8f4ee66..02fc124179bd7f636140bd5d0afbbebecf66198f 100644
--- a/app/i18n/Magento/zh_CN/language.xml
+++ b/app/i18n/magento/zh_cn/language.xml
@@ -25,5 +25,6 @@
 -->
 <language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
     <code>zh_CN</code>
-    <vendor>Magento</vendor>
+    <vendor>magento</vendor>
+    <package>zh_cn</package>
 </language>
diff --git a/dev/tests/functional/.htaccess b/dev/tests/functional/.htaccess
index 0a28bdaf0303a310ed6612bcd1751c0b2bf5bdee..db0b8f66ad0008c5f765391d0b93515d711ab1b7 100644
--- a/dev/tests/functional/.htaccess
+++ b/dev/tests/functional/.htaccess
@@ -191,4 +191,4 @@
 ## If running in cluster environment, uncomment this
 ## http://developer.yahoo.com/performance/rules.html#etags
 
-    #FileETag none
+    #FileETag none
\ No newline at end of file
diff --git a/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/ConditionsElement.php b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/ConditionsElement.php
index e8d5572c9354efbef0961dcd062dca3f341b6a3f..4fee295b916d85f755248fa68b91db0fd1ecaeac 100644
--- a/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/ConditionsElement.php
+++ b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/ConditionsElement.php
@@ -27,6 +27,7 @@ namespace Mtf\Client\Driver\Selenium\Element;
 use Mtf\Client\Element;
 use Mtf\Client\Element\Locator;
 use Mtf\Client\Driver\Selenium\Element as AbstractElement;
+use Mtf\ObjectManager;
 
 /**
  * Class ConditionsElement
@@ -61,6 +62,13 @@ class ConditionsElement extends AbstractElement
      */
     protected $mainCondition = './/ul[contains(@id,"__1__children")]/..';
 
+    /**
+     * Identification for chooser grid
+     *
+     * @var string
+     */
+    protected $chooserLocator = '.rule-chooser-trigger';
+
     /**
      * Button add condition
      *
@@ -163,6 +171,13 @@ class ConditionsElement extends AbstractElement
      */
     protected $loader = './/ancestor::body/div[@id="loading-mask"]';
 
+    /**
+     * Chooser grid locator
+     *
+     * @var string
+     */
+    protected $chooserGridLocator = 'div[id*=chooser]';
+
     /**
      * Set value to conditions
      *
@@ -254,6 +269,20 @@ class ConditionsElement extends AbstractElement
             $param = $this->findNextParam($element);
             $param->find('a')->click();
 
+            if (preg_match('`%(.*?)%`', $rule, $chooserGrid)) {
+                $chooserConfig = explode('#', $chooserGrid[1]);
+                $param->find($this->chooserLocator)->click();
+                $rule = preg_replace('`%(.*?)%`', '', $rule);
+                $grid = ObjectManager::getInstance()->create(
+                    str_replace('/', '\\', $chooserConfig[0]),
+                    [
+                        'element' => $this->find($this->chooserGridLocator)
+                    ]
+                );
+                $grid->searchAndSelect([$chooserConfig[1] => $rule]);
+                continue;
+            }
+
             $value = $param->find('select', Locator::SELECTOR_CSS, 'select');
             if ($value->isVisible()) {
                 $value->setValue($rule);
diff --git a/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/DatepickerElement.php b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/DatepickerElement.php
index 39b76ffce6e2bf20cefc8db0fe2881deff8e2cf1..5d1f89325ac503c109a9f5f0ceedf8d694711714 100644
--- a/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/DatepickerElement.php
+++ b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/DatepickerElement.php
@@ -85,13 +85,15 @@ class DatepickerElement extends Element
     public function setValue($value)
     {
         $date = $this->parseDate($value);
-
+        $date[1] = ltrim($date[1], '0');
         $this->find($this->datePickerButton, Locator::SELECTOR_XPATH)->click();
         $datapicker = $this->find($this->datePickerBlock, Locator::SELECTOR_XPATH);
         $datapicker->find($this->datePickerMonth, Locator::SELECTOR_XPATH, 'select')->setValue($date[0]);
         $datapicker->find($this->datePickerYear, Locator::SELECTOR_XPATH, 'select')->setValue($date[2]);
         $datapicker->find(sprintf($this->datePickerCalendar, $date[1]), Locator::SELECTOR_XPATH)->click();
-        $datapicker->find($this->datePickerButtonClose, Locator::SELECTOR_XPATH)->click();
+        if ($datapicker->isVisible()) {
+            $datapicker->find($this->datePickerButtonClose, Locator::SELECTOR_XPATH)->click();
+        }
     }
 
     /**
diff --git a/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/JquerytreeElement.php b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/JquerytreeElement.php
index 2f6a7c38982d43b10fad305c3837930a521c046d..db5ce08dc54af680617b711716ceaa37efa307f8 100644
--- a/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/JquerytreeElement.php
+++ b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/JquerytreeElement.php
@@ -175,6 +175,6 @@ class JquerytreeElement extends Tree
         foreach ($pathsArray as $pathArray) {
             $this->getPathFromArray($pathArray);
         }
-        return $this->checkedNodesPaths;
+        return array_filter($this->checkedNodesPaths);
     }
 }
diff --git a/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/MultisuggestElement.php b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/MultisuggestElement.php
new file mode 100644
index 0000000000000000000000000000000000000000..e2cfe0991ffd3744555f2a5ad5b87499087fdb95
--- /dev/null
+++ b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/MultisuggestElement.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Mtf\Client\Driver\Selenium\Element;
+
+use Mtf\Client\Driver\Selenium\Element;
+use Mtf\Client\Element\Locator;
+
+/**
+ * Class MultisuggestElement
+ * Typified element class for multi suggest element
+ */
+class MultisuggestElement extends SuggestElement
+{
+    /**
+     * Selector list choice
+     *
+     * @var string
+     */
+    protected $listChoice = './/ul[contains(@class,"mage-suggest-choices")]';
+
+    /**
+     * Selector choice item
+     *
+     * @var string
+     */
+    protected $choice = './/li/div[text()="%s"]/..';
+
+    /**
+     * Selector choice value
+     *
+     * @var string
+     */
+    protected $choiceValue = './/li[contains(@class,"mage-suggest-choice")]/div';
+
+    /**
+     * Selector remove choice item
+     *
+     * @var string
+     */
+    protected $choiceClose = '.mage-suggest-choice-close';
+
+    /**
+     * Set value
+     *
+     * @param array|string $values
+     * @return void
+     */
+    public function setValue($values)
+    {
+        $this->_eventManager->dispatchEvent(['set_value'], [__METHOD__, $this->getAbsoluteSelector()]);
+
+        $this->clear();
+        foreach ((array)$values as $value) {
+            if (!$this->isChoice($value)) {
+                parent::setValue($value);
+            }
+        }
+    }
+
+    /**
+     * Get value
+     *
+     * @return array
+     */
+    public function getValue()
+    {
+        $this->_eventManager->dispatchEvent(['get_value'], [(string) $this->_locator]);
+
+        $listChoice = $this->find($this->listChoice, Locator::SELECTOR_XPATH);
+        $choices = $listChoice->find($this->choiceValue, Locator::SELECTOR_XPATH)->getElements();
+        $values = [];
+
+        foreach ($choices as $choice) {
+            /** @var Element $choice */
+            $values[] = $choice->getText();
+        }
+        return $values;
+    }
+
+    /**
+     * Check exist selected item
+     *
+     * @param string $value
+     * @return bool
+     */
+    protected function isChoice($value)
+    {
+        return $this->find(sprintf($this->choice, $value), Locator::SELECTOR_XPATH)->isVisible();
+    }
+
+    /**
+     * Clear element
+     *
+     * @return void
+     */
+    protected function clear()
+    {
+        $choiceClose = $this->find($this->choiceClose);
+        while ($choiceClose->isVisible()) {
+            $choiceClose->click();
+            $choiceClose = $this->find($this->choiceClose);
+        }
+    }
+}
diff --git a/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/SuggestElement.php b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/SuggestElement.php
old mode 100644
new mode 100755
index aca42a1d95feacc104340cec9a0cbf9aa4865a32..a1d028108947cc93f113c125d0d7fe415d8295df
--- a/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/SuggestElement.php
+++ b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/SuggestElement.php
@@ -62,6 +62,8 @@ class SuggestElement extends Element
      */
     public function setValue($value)
     {
+        $this->_eventManager->dispatchEvent(['set_value'], [__METHOD__, $this->getAbsoluteSelector()]);
+
         $this->find($this->suggest)->setValue($value);
         $this->waitResult();
         $this->find(sprintf($this->resultItem, $value), Locator::SELECTOR_XPATH)->click();
@@ -90,6 +92,8 @@ class SuggestElement extends Element
      */
     public function getValue()
     {
+        $this->_eventManager->dispatchEvent(['get_value'], [(string) $this->_locator]);
+        
         return $this->find($this->suggest)->getValue();
     }
 }
diff --git a/dev/tests/functional/lib/Mtf/Constraint/AbstractAssertForm.php b/dev/tests/functional/lib/Mtf/Constraint/AbstractAssertForm.php
index 32b2d087b110ba4794dc81178adc002b522965e7..76198d9674d088d82edf86dfe3b2a032f7b2dd45 100755
--- a/dev/tests/functional/lib/Mtf/Constraint/AbstractAssertForm.php
+++ b/dev/tests/functional/lib/Mtf/Constraint/AbstractAssertForm.php
@@ -27,9 +27,19 @@ namespace Mtf\Constraint;
 /**
  * Class AssertForm
  * Abstract class AssertForm
+ * Implements:
+ *  - verify fixture data and form data
+ *  - sort multidimensional array by paths
  */
 abstract class AbstractAssertForm extends AbstractConstraint
 {
+    /**
+     * Skipped fields for verify data
+     *
+     * @var array
+     */
+    protected $skippedFields = [];
+
     /**
      * Verify fixture and form data
      *
@@ -47,6 +57,9 @@ abstract class AbstractAssertForm extends AbstractConstraint
         $errors = [];
 
         foreach ($fixtureData as $key => $value) {
+            if (in_array($key, $this->skippedFields)) {
+                continue;
+            }
             $formValue = isset($formData[$key]) ? $formData[$key] : null;
             if (is_numeric($formValue)) {
                 $formValue = floatval($formValue);
@@ -83,40 +96,95 @@ abstract class AbstractAssertForm extends AbstractConstraint
         return $errors;
     }
 
+    /**
+     * Sort array by value
+     *
+     * @param array $data
+     * @return array
+     */
+    protected function sortData(array $data)
+    {
+        $scalarValues = [];
+        $arrayValues = [];
+
+        foreach ($data as $key => $value) {
+            if (is_array($value)) {
+                $arrayValues[$key] = $this->dataSort($value);
+            } else {
+                $scalarValues[$key] = $value;
+            }
+        }
+        asort($scalarValues);
+        foreach (array_keys($arrayValues) as $key) {
+            if (!is_numeric($key)) {
+                ksort($arrayValues);
+                break;
+            }
+        }
+
+        return $scalarValues + $arrayValues;
+    }
+
     /**
      * Sort multidimensional array by paths
+     * Pattern path: key/subKey::sorkKey.
+     * Exapmle:
+     * $data = [
+     *     'custom_options' => [
+     *         'options' => [
+     *             0 => [
+     *                 'title' => 'title_2',
+     *             ],
+     *             1 => [
+     *                 'title' => 'title_1'
+     *             ]
+     *         ]
+     *     ]
+     * ];
+     * $paths = ['custom_options/options::title'];
+     *
+     * Result:
+     * $data = [
+     *     'custom_options' => [
+     *         'options' => [
+     *             title_1 => [
+     *                 'title' => 'title_1',
+     *             ],
+     *             title_2 => [
+     *                 'title' => 'title_2'
+     *             ]
+     *         ]
+     *     ]
+     * ];
      *
      * @param array $data
-     * @param array|string $paths
+     * @param string $path
+     * @param string $path
      * @return array
+     * @throws \Exception
+     *
+     * @SuppressWarnings(PHPMD.NPathComplexity)
      */
-    protected function sortData(array $data, $paths)
+    protected function sortDataByPath(array $data, $path)
     {
-        $paths = is_array($paths) ? $paths : [$paths];
-        foreach ($paths as $path) {
-            $values = &$data;
-            $keys = explode('/', $path);
-
-            $key = array_shift($keys);
-            $order = null;
-            while (null !== $key) {
-                if (false !== strpos($key, '::')) {
-                    list($key, $order) = explode('::', $key);
-                }
-                if ($key && !isset($values[$key])) {
-                    $key = null;
-                    continue;
-                }
+        $steps = explode('/', $path);
+        $key = array_shift($steps);
+        $order = null;
+        $nextPath = empty($steps) ? null : implode('/', $steps);
 
-                if ($key) {
-                    $values = &$values[$key];
-                }
-                if ($order) {
-                    $values = $this->sortMultidimensionalArray($values, $order);
-                    $order = null;
-                }
-                $key = array_shift($keys);
-            }
+        if (false !== strpos($key, '::')) {
+            list($key, $order) = explode('::', $key);
+        }
+        if ($key && !isset($data[$key])) {
+            return $data;
+        }
+
+        if ($key) {
+            $data[$key] = $order ? $this->sortMultidimensionalArray($data[$key], $order) : $data[$key];
+            $data[$key] = $nextPath ? $this->sortData($data[$key], $nextPath) : $data[$key];
+        } else {
+            $data = $this->sortMultidimensionalArray($data, $order);
+            $data = $nextPath ? $this->sortData($data, $nextPath) : $data;
         }
 
         return $data;
@@ -133,7 +201,8 @@ abstract class AbstractAssertForm extends AbstractConstraint
     {
         $result = [];
         foreach ($data as $value) {
-            $result[$value[$key]] = $value;
+            $sortKey = is_numeric($value[$key]) ? floatval($value[$key]) : $value[$key];
+            $result[$sortKey] = $value;
         }
 
         ksort($result);
@@ -162,7 +231,7 @@ abstract class AbstractAssertForm extends AbstractConstraint
      *
      * @param array $errors
      * @param string|null $notice
-     * @param string $indent
+     * @param string $indent [optional]
      * @return string
      */
     protected function prepareErrors(array $errors, $notice = null, $indent = '')
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/FormPageActions.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/FormPageActions.php
index a17327a5c59d18e0c4de538248f64b40aac512b5..24ba6559bde71a7cbea18238191c05849f1eeee5 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/FormPageActions.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/FormPageActions.php
@@ -29,6 +29,8 @@ use Mtf\Client\Element\Locator;
 /**
  * Class FormPageActions
  * Form page actions block
+ *
+ * @SuppressWarnings(PHPMD.NumberOfChildren)
  */
 class FormPageActions extends PageActions
 {
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Delete/StoreForm.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Delete/StoreForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..87172a11980baea1fed34be69a7f5aa74b94fc51
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Delete/StoreForm.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Backend\Test\Block\System\Store\Delete;
+
+use Mtf\Client\Element;
+use Mtf\Block\Form;
+use Mtf\Client\Element\Locator;
+
+/**
+ * Class StoreForm
+ * Form for Store View deletion
+ */
+class StoreForm extends Form
+{
+    /**
+     * Fill Backup Option in Delete Store View
+     *
+     * @param array $data
+     * @param Element $element
+     * @return void
+     */
+    public function fillForm(array $data, Element $element = null)
+    {
+        $mapping = $this->dataMapping($data);
+        $this->_fill($mapping, $element);
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Delete/StoreForm.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Delete/StoreForm.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5e6ba1de31c497befe3c885fdc932d318426271a
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Delete/StoreForm.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <create_backup>
+            <selector>[name="create_backup"]</selector>
+            <input>select</input>
+        </create_backup>
+    </fields>
+</mapping>
\ No newline at end of file
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Edit.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Edit/StoreForm.php
similarity index 83%
rename from dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Edit.php
rename to dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Edit/StoreForm.php
index 9792e3fa085316bb519c49f630196ce16220b7da..f093986d7f123041033d76178f2a4922d8e5c80c 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Edit.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Edit/StoreForm.php
@@ -1,7 +1,5 @@
 <?php
 /**
- * Store edit form
- *
  * Magento
  *
  * NOTICE OF LICENSE
@@ -24,14 +22,15 @@
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
 
-namespace Magento\Backend\Test\Block\System\Store;
+namespace Magento\Backend\Test\Block\System\Store\Edit;
+
+use Mtf\Block\Form;
 
 /**
- * Class Edit
- * Adminhtml store content block
- *
+ * Class StoreForm
+ * Form for Store View creation
  */
-class Edit extends \Magento\Backend\Test\Block\Widget\Form
+class StoreForm extends Form
 {
     //
 }
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Edit.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Edit/StoreForm.xml
similarity index 87%
rename from dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Edit.xml
rename to dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Edit/StoreForm.xml
index 8b0c89b7de33e14cd2cb61045cf078215140c1ab..17e1c7b63a9abf28b8f677280d0abd477e13099a 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Edit.xml
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Edit/StoreForm.xml
@@ -26,15 +26,11 @@
 <mapping strict="0">
     <wrapper>store</wrapper>
     <fields>
-        <group>
-            <selector>[name='store[group_id]']</selector>
+        <group_id>
             <input>select</input>
-        </group>
-        <name />
-        <code />
+        </group_id>
         <is_active>
             <input>select</input>
         </is_active>
-        <sort_order />
     </fields>
-</mapping>
+</mapping>
\ No newline at end of file
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Grid.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/FormPageActions.php
similarity index 73%
rename from dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Grid.php
rename to dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/FormPageActions.php
index f36cfae3edcdb2b1afcfbc402e8a25294f41c0a5..7ab073981dac5b0c76298fed3e9767fe38f903a2 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Grid.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/FormPageActions.php
@@ -1,7 +1,5 @@
 <?php
 /**
- * Store grid
- *
  * Magento
  *
  * NOTICE OF LICENSE
@@ -23,21 +21,24 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
+
 namespace Magento\Backend\Test\Block\System\Store;
 
-use Mtf\Client\Element\Locator;
+use Magento\Backend\Test\Block\FormPageActions as ParentFormPageActions;
 
-class Grid extends \Magento\Backend\Test\Block\Widget\Grid
+/**
+ * Class FormPageActions
+ * Form page actions block in Store page
+ */
+class FormPageActions extends ParentFormPageActions
 {
     /**
-     * Check if store exists
+     * Click on "Delete" button without acceptAlert
      *
-     * @param string $title
-     * @return bool
+     * @return void
      */
-    public function isStoreExists($title)
+    public function delete()
     {
-        $element = $this->_rootElement->find($title, Locator::SELECTOR_LINK_TEXT);
-        return $element && $element->isVisible();
+        $this->_rootElement->find($this->deleteButton)->click();
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/GridPageActions.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/GridPageActions.php
new file mode 100644
index 0000000000000000000000000000000000000000..66151d69496dcf429ee28de5c09d9eaa6ceb0f76
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/GridPageActions.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Backend\Test\Block\System\Store;
+
+use Magento\Backend\Test\Block\GridPageActions as ParentGridPageActions;
+
+/**
+ * Class GridPageActions
+ * Grid page actions block in Cms Block grid page
+ */
+class GridPageActions extends ParentGridPageActions
+{
+    /**
+     * Add Store View button
+     *
+     * @var string
+     */
+    protected $addStoreViewButton = '#add_store';
+
+    /**
+     * Click on Add Store View button
+     *
+     * @return void
+     */
+    public function addStoreView()
+    {
+        $this->_rootElement->find($this->addStoreViewButton)->click();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/StoreGrid.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/StoreGrid.php
new file mode 100644
index 0000000000000000000000000000000000000000..71da0c14b80811d018120f20bf3e243a3126d894
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/StoreGrid.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Backend\Test\Block\System\Store;
+
+use Mtf\Client\Element\Locator;
+use Magento\Backend\Test\Block\Widget\Grid as GridInterface;
+
+/**
+ * Class StoreGrid
+ * Adminhtml Store View management grid
+ */
+class StoreGrid extends GridInterface
+{
+    /**
+     * Locator value for opening needed row
+     *
+     * @var string
+     */
+    protected $editLink = 'td[data-column="store_title"] > a';
+
+    /**
+     * Filters array mapping
+     *
+     * @var array
+     */
+    protected $filters = [
+        'store_title' => [
+            'selector' => '#storeGrid_filter_store_title',
+        ],
+    ];
+
+    /**
+     * Store title format for XPATH
+     *
+     * @var string
+     */
+    protected $titleFormat = '//td[a[.="%s"]]';
+
+    /**
+     * Check if store exists
+     *
+     * @param string $title
+     * @return bool
+     */
+    public function isStoreExists($title)
+    {
+        $element = $this->_rootElement->find(sprintf($this->titleFormat, $title), Locator::SELECTOR_XPATH);
+        return $element->isVisible();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Variable/Edit/VariableForm.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Variable/Edit/VariableForm.xml
index c103192abb9d3556bbfdb2fcc4f71d14d34f78f0..b21f663a2e7dc6140b97c4c49dd3817d2b0b67fc 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Variable/Edit/VariableForm.xml
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Variable/Edit/VariableForm.xml
@@ -28,6 +28,9 @@
     <fields>
         <code />
         <name />
+        <use_default_value>
+            <input>select</input>
+        </use_default_value>
         <html_value />
         <plain_value />
     </fields>
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreDelete.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreDelete.php
new file mode 100644
index 0000000000000000000000000000000000000000..094121f227de0959ca6798269f0f6affd957df39
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreDelete.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Backend\Test\Page\Adminhtml;
+
+use Mtf\Page\BackendPage;
+
+/**
+ * Class StoreDelete
+ * Backend Store delete page
+ */
+class StoreDelete extends BackendPage
+{
+    const MCA = 'admin/system_store/deleteStore';
+
+    protected $_blocks = [
+        'messagesBlock' => [
+            'name' => 'messagesBlock',
+            'class' => 'Magento\Core\Test\Block\Messages',
+            'locator' => '#messages',
+            'strategy' => 'css selector',
+        ],
+        'storeForm' => [
+            'name' => 'form',
+            'class' => 'Magento\Backend\Test\Block\System\Store\Delete\StoreForm',
+            'locator' => '#edit_form',
+            'strategy' => 'css selector',
+        ],
+        'formPageActions' => [
+            'name' => 'formPageActions',
+            'class' => 'Magento\Backend\Test\Block\System\Store\FormPageActions',
+            'locator' => '.content-footer',
+            'strategy' => 'css selector',
+        ],
+    ];
+
+    /**
+     * @return \Magento\Core\Test\Block\Messages
+     */
+    public function getMessagesBlock()
+    {
+        return $this->getBlockInstance('messagesBlock');
+    }
+
+    /**
+     * @return \Magento\Backend\Test\Block\System\Store\Delete\StoreForm
+     */
+    public function getStoreForm()
+    {
+        return $this->getBlockInstance('storeForm');
+    }
+
+    /**
+     * @return \Magento\Backend\Test\Block\System\Store\FormPageActions
+     */
+    public function getFormPageActions()
+    {
+        return $this->getBlockInstance('formPageActions');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreDelete.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreDelete.xml
new file mode 100644
index 0000000000000000000000000000000000000000..54f0501806f2d67e6f349a572a0d6768979bd7c9
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreDelete.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<page mca="admin/system_store/deleteStore" >
+    <block>
+        <name>messagesBlock</name>
+        <class>Magento\Core\Test\Block\Messages</class>
+        <locator>#messages</locator>
+        <strategy>css selector</strategy>
+    </block>
+    <block>
+        <name>storeForm</name>
+        <class>Magento\Backend\Test\Block\System\Store\Delete\StoreForm</class>
+        <locator>#edit_form</locator>
+        <strategy>css selector</strategy>
+    </block>
+    <block>
+        <name>formPageActions</name>
+        <class>Magento\Backend\Test\Block\System\Store\FormPageActions</class>
+        <locator>.content-footer</locator>
+        <strategy>css selector</strategy>
+    </block>
+</page>
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreIndex.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreIndex.php
new file mode 100644
index 0000000000000000000000000000000000000000..363ccc5a128f6aacef40201ddeafc16588ec44b9
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreIndex.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Backend\Test\Page\Adminhtml;
+
+use Mtf\Page\BackendPage;
+
+/**
+ * Class StoreIndex
+ * Backend Store index page
+ */
+class StoreIndex extends BackendPage
+{
+    const MCA = 'admin/system_store';
+
+    protected $_blocks = [
+        'messagesBlock' => [
+            'name' => 'messagesBlock',
+            'class' => 'Magento\Core\Test\Block\Messages',
+            'locator' => '#messages',
+            'strategy' => 'css selector',
+        ],
+        'gridPageActions' => [
+            'name' => 'gridPageActions',
+            'class' => 'Magento\Backend\Test\Block\System\Store\GridPageActions',
+            'locator' => '.page-main-actions',
+            'strategy' => 'css selector',
+        ],
+        'storeGrid' => [
+            'name' => 'storeGrid',
+            'class' => 'Magento\Backend\Test\Block\System\Store\StoreGrid',
+            'locator' => '[id="page:main-container"]',
+            'strategy' => 'css selector',
+        ],
+    ];
+
+    /**
+     * @return \Magento\Core\Test\Block\Messages
+     */
+    public function getMessagesBlock()
+    {
+        return $this->getBlockInstance('messagesBlock');
+    }
+
+    /**
+     * @return \Magento\Backend\Test\Block\System\Store\GridPageActions
+     */
+    public function getGridPageActions()
+    {
+        return $this->getBlockInstance('gridPageActions');
+    }
+
+    /**
+     * @return \Magento\Backend\Test\Block\System\Store\StoreGrid
+     */
+    public function getStoreGrid()
+    {
+        return $this->getBlockInstance('storeGrid');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreIndex.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreIndex.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6e858a105199bb5d9d7eb50253c1ec078468f1c0
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreIndex.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<page mca="admin/system_store" >
+    <block>
+        <name>messagesBlock</name>
+        <class>Magento\Core\Test\Block\Messages</class>
+        <locator>#messages</locator>
+        <strategy>css selector</strategy>
+    </block>
+    <block>
+        <name>gridPageActions</name>
+        <class>Magento\Backend\Test\Block\System\Store\GridPageActions</class>
+        <locator>.page-main-actions</locator>
+        <strategy>css selector</strategy>
+    </block>
+    <block>
+        <name>storeGrid</name>
+        <class>Magento\Backend\Test\Block\System\Store\StoreGrid</class>
+        <locator>[id="page:main-container"]</locator>
+        <strategy>css selector</strategy>
+    </block>
+</page>
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreNew.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreNew.php
new file mode 100644
index 0000000000000000000000000000000000000000..5a965e4adad39986648984040aefe18978048456
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreNew.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Backend\Test\Page\Adminhtml;
+
+use Mtf\Page\BackendPage;
+
+/**
+ * Class StoreNew
+ * Backend new Store page
+ */
+class StoreNew extends BackendPage
+{
+    const MCA = 'admin/system_store/newStore';
+
+    protected $_blocks = [
+        'formPageActions' => [
+            'name' => 'formPageActions',
+            'class' => 'Magento\Backend\Test\Block\System\Store\FormPageActions',
+            'locator' => '.page-main-actions',
+            'strategy' => 'css selector',
+        ],
+        'storeForm' => [
+            'name' => 'storeForm',
+            'class' => 'Magento\Backend\Test\Block\System\Store\Edit\StoreForm',
+            'locator' => '[id="page:main-container"]',
+            'strategy' => 'css selector',
+        ],
+        'messagesBlock' => [
+            'name' => 'messagesBlock',
+            'class' => 'Magento\Core\Test\Block\Messages',
+            'locator' => '#messages',
+            'strategy' => 'css selector',
+        ],
+    ];
+
+    /**
+     * @return \Magento\Backend\Test\Block\System\Store\FormPageActions
+     */
+    public function getFormPageActions()
+    {
+        return $this->getBlockInstance('formPageActions');
+    }
+
+    /**
+     * @return \Magento\Backend\Test\Block\System\Store\Edit\StoreForm
+     */
+    public function getStoreForm()
+    {
+        return $this->getBlockInstance('storeForm');
+    }
+
+    /**
+     * @return \Magento\Core\Test\Block\Messages
+     */
+    public function getMessagesBlock()
+    {
+        return $this->getBlockInstance('messagesBlock');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreNew.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreNew.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5fd621e3fbc0fda6c755b63e115cf658bf1f8b99
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/Adminhtml/StoreNew.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<page mca="admin/system_store/newStore" >
+    <block>
+        <name>formPageActions</name>
+        <class>Magento\Backend\Test\Block\System\Store\FormPageActions</class>
+        <locator>.page-main-actions</locator>
+        <strategy>css selector</strategy>
+    </block>
+    <block>
+        <name>storeForm</name>
+        <class>Magento\Backend\Test\Block\System\Store\Edit\StoreForm</class>
+        <locator>[id="page:main-container"]</locator>
+        <strategy>css selector</strategy>
+    </block>
+    <block>
+        <name>messagesBlock</name>
+        <class>Magento\Core\Test\Block\Messages</class>
+        <locator>#messages</locator>
+        <strategy>css selector</strategy>
+    </block>
+</page>
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/System/Store/ItemList.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/System/Store/ItemList.php
deleted file mode 100644
index 82efd6173bc78f0b417bc02c740a4a45d993ad00..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/System/Store/ItemList.php
+++ /dev/null
@@ -1,101 +0,0 @@
-<?php
-/**
- * Store list page
- *
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
- */
-namespace Magento\Backend\Test\Page\System\Store;
-
-use Mtf\Page\Page;
-use Mtf\Factory\Factory;
-use \Magento\Core\Test\Block\Messages;
-use \Magento\Backend\Test\Block\System\Store\Actions;
-use \Magento\Backend\Test\Block\System\Store\Grid;
-
-class ItemList extends Page
-{
-    /**
-     * Url
-     */
-    const MCA = 'admin/system_store';
-
-    /**
-     * Messages block selector
-     *
-     * @var string
-     */
-    protected $messagesBlock = '#messages .messages';
-
-    /**
-     * Actions block selector
-     *
-     * @var string
-     */
-    protected $pageActionsBlock = '.page-actions';
-
-    /**
-     * Store grid selector
-     *
-     * @var string
-     */
-    protected $gridBlock = '#storeGrid';
-
-    /**
-     * Constructor
-     */
-    protected function _init()
-    {
-        $this->_url = $_ENV['app_backend_url'] . self::MCA;
-    }
-
-    /**
-     * Retrieve  actions block
-     *
-     * @return Actions
-     */
-    public function getPageActionsBlock()
-    {
-        return Factory::getBlockFactory()->getMagentoBackendSystemStoreActions(
-            $this->_browser->find($this->pageActionsBlock)
-        );
-    }
-
-    /**
-     * Retrieve store grid block
-     *
-     * @return Grid
-     */
-    public function getGridBlock()
-    {
-        return Factory::getBlockFactory()->getMagentoBackendSystemStoreGrid($this->_browser->find($this->gridBlock));
-    }
-
-    /**
-     * Retrieve messages block
-     *
-     * @return Messages
-     */
-    public function getMessagesBlock()
-    {
-        return Factory::getBlockFactory()->getMagentoCoreMessages($this->_browser->find($this->messagesBlock));
-    }
-}
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/System/Store/NewStore.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Page/System/Store/NewStore.php
deleted file mode 100644
index 35a9b14d68e9887375c7ee4d0f14b20da0ca372d..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Page/System/Store/NewStore.php
+++ /dev/null
@@ -1,79 +0,0 @@
-<?php
-/**
- * Store creation page
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
- */
-namespace Magento\Backend\Test\Page\System\Store;
-
-use Mtf\Factory\Factory;
-use Mtf\Page\Page;
-
-class NewStore extends Page
-{
-    const MCA = 'admin/system_store/newStore';
-
-    /**
-     * Store edit form block
-     *
-     * @var string
-     */
-    protected $formBlock = '#edit_form';
-
-    /**
-     * Page actions block
-     *
-     * @var string
-     */
-    protected $actionsBlock = '.page-actions';
-
-    /**
-     * Initialize page
-     */
-    protected function _init()
-    {
-        $this->_url = $_ENV['app_frontend_url'] . self::MCA;
-    }
-
-    /**
-     * Retrieve form block
-     *
-     * @return \Magento\Backend\Test\Block\System\Store\Edit
-     */
-    public function getFormBlock()
-    {
-        return Factory::getBlockFactory()->getMagentoBackendSystemStoreEdit(
-            $this->_browser->find($this->formBlock)
-        );
-    }
-
-    /**
-     * Retrieve actions block
-     *
-     * @return \Magento\Backend\Test\Block\System\Store\Actions
-     */
-    public function getPageActionsBlock()
-    {
-        return Factory::getBlockFactory()->getMagentoBackendSystemStoreActions(
-            $this->_browser->find($this->actionsBlock)
-        );
-    }
-}
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/etc/global/page.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/etc/global/page.xml
index 9085814b562432a3a061319b8cfb56bc089a6357..7706202b03c56e5cd80cea5df9690813122088e4 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/etc/global/page.xml
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/etc/global/page.xml
@@ -24,9 +24,24 @@
  */
 -->
 <page>
-    <config>
+    <systemConfig>
         <mca>admin/system_config</mca>
         <area>adminhtml</area>
         <class>Magento\Backend\Test\Page\Adminhtml\SystemConfig</class>
-    </config>
+    </systemConfig>
+    <systemStoreIndex>
+        <mca>admin/system_store</mca>
+        <area>adminhtml</area>
+        <class>Magento\Backend\Test\Page\Adminhtml\StoreIndex</class>
+    </systemStoreIndex>
+    <systemStoreNew>
+        <mca>admin/system_store/newStore</mca>
+        <area>adminhtml</area>
+        <class>Magento\Backend\Test\Page\Adminhtml\StoreNew</class>
+    </systemStoreNew>
+    <systemStoreDelete>
+        <mca>admin/system_store/deleteStore</mca>
+        <area>adminhtml</area>
+        <class>Magento\Backend\Test\Page\Adminhtml\StoreDelete</class>
+    </systemStoreDelete>
 </page>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle.php
index bcaf9cbb617912ecbf37f97d7c9788a719112219..ff2a43e7792e9c4b5d2033b983d4ab0ab117d8ed 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle.php
@@ -25,40 +25,40 @@
 namespace Magento\Bundle\Test\Block\Adminhtml\Catalog\Product\Edit\Tab;
 
 use Mtf\Client\Element;
-use Mtf\Factory\Factory;
 use Magento\Backend\Test\Block\Widget\Tab;
-use Magento\Catalog\Test\Fixture\CatalogProductSimple;
+use Magento\Bundle\Test\Block\Adminhtml\Catalog\Product\Edit\Tab\Bundle\Option;
 
 /**
  * Class Bundle
- * Bundle options section
+ * Bundle options section block on product-details tab
  */
 class Bundle extends Tab
 {
     /**
-     * 'Create New Option' button
+     * Selector for 'Create New Option' button
      *
      * @var string
      */
     protected $addNewOption = '#add_new_option';
 
     /**
-     * Bundle options block
+     * Open option section
      *
      * @var string
      */
-    protected $bundleOptionBlock = '#bundle_option_';
+    protected $openOption = '[data-target="#bundle_option_%d-content"]';
 
     /**
      * Get bundle options block
      *
      * @param int $blockNumber
-     * @return \Magento\Bundle\Test\Block\Adminhtml\Catalog\Product\Edit\Tab\Bundle\Option
+     * @return Option
      */
     protected function getBundleOptionBlock($blockNumber)
     {
-        return Factory::getBlockFactory()->getMagentoBundleAdminhtmlCatalogProductEditTabBundleOption(
-            $this->_rootElement->find($this->bundleOptionBlock . $blockNumber)
+        return $this->blockFactory->create(
+            'Magento\Bundle\Test\Block\Adminhtml\Catalog\Product\Edit\Tab\Bundle\Option',
+            ['element' => $this->_rootElement->find('#bundle_option_' . $blockNumber)]
         );
     }
 
@@ -74,68 +74,42 @@ class Bundle extends Tab
         if (!isset($fields['bundle_selections'])) {
             return $this;
         }
-        $bundleOptions = $this->prepareBundleOptions($fields['bundle_selections']['value']['bundle_options']);
-        $blocksNumber = 0;
-        foreach ($bundleOptions as $bundleOption) {
-            $this->_rootElement->find($this->addNewOption)->click();
-            $bundleOptionsBlock = $this->getBundleOptionBlock($blocksNumber);
-            $bundleOptionsBlock->fillBundleOption($bundleOption, $this->_rootElement);
-            $blocksNumber++;
+        foreach ($fields['bundle_selections']['value']['bundle_options'] as $key => $bundleOption) {
+            $itemOption = $this->_rootElement->find(sprintf($this->openOption, $key));
+            if ($itemOption->isVisible()) {
+                $itemOption->click();
+            } else {
+                $this->_rootElement->find($this->addNewOption)->click();
+            }
+            $this->getBundleOptionBlock($key)->fillBundleOption($bundleOption);
         }
-
         return $this;
     }
 
     /**
-     * Update bundle options
+     * Get data to fields on downloadable tab
      *
-     * @param array $fields
+     * @param array|null $fields
      * @param Element|null $element
-     * @return void
-     */
-    public function updateFormTab(array $fields, Element $element = null)
-    {
-        if (!isset($fields['bundle_selections'])) {
-            return;
-        }
-        $bundleOptions = $this->prepareBundleOptions($fields['bundle_selections']['value']);
-        $blocksNumber = 0;
-        foreach ($$bundleOptions as $bundleOption) {
-            $bundleOptionsBlock = $this->getBundleOptionBlock($blocksNumber, $element);
-            $bundleOptionsBlock->expand();
-            $bundleOptionsBlock->updateBundleOption($bundleOption, $element);
-            $blocksNumber++;
-        }
-    }
-
-    /**
-     * Prepare Bundle Options array from preset
-     *
-     * @param array $bundleSelections
      * @return array
-     * @throws \InvalidArgumentException
      */
-    protected function prepareBundleOptions(array $bundleSelections)
+    public function getDataFormTab($fields = null, Element $element = null)
     {
-        if (!isset($bundleSelections['preset'])) {
-            return $bundleSelections;
+        $newFields = [];
+        if (!isset($fields['bundle_selections'])) {
+            return $this;
         }
-
-        $preset = $bundleSelections['preset'];
-        $products = $bundleSelections['products'];
-        foreach ($preset['items'] as & $item) {
-            foreach ($item['assigned_products'] as $productIncrement => & $selection) {
-                if (!isset($products[$productIncrement])) {
-                    throw new \InvalidArgumentException(
-                        sprintf('Not sufficient number of products for bundle preset: %s', $preset['name'])
-                    );
-                }
-                /** @var $fixture CatalogProductSimple */
-                $fixture = $products[$productIncrement];
-                $selection['search_data']['name'] = $fixture->getName();
-                $selection['data']['product_id']['value'] = $fixture->getId();
+        $index = 0;
+        foreach ($fields['bundle_selections']['value']['bundle_options'] as $key => &$bundleOption) {
+            $this->_rootElement->find(sprintf($this->openOption, $index))->click();
+            foreach ($bundleOption['assigned_products'] as &$product) {
+                $product['data']['getProductName'] = $product['search_data']['name'];
             }
+            $newFields['bundle_selections'][$key] = $this->getBundleOptionBlock($key)
+                ->getBundleOptionData($bundleOption);
+            $index++;
         }
-        return $preset['items'];
+
+        return $newFields;
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.php
index 5aacc6f8d6f65bf14016c57848d81fab696b7926..cf1ae7edca2b8dc40706b995d05a70d3a7a21ec0 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.php
@@ -24,19 +24,20 @@
 
 namespace Magento\Bundle\Test\Block\Adminhtml\Catalog\Product\Edit\Tab\Bundle;
 
-use Mtf\Block\Block;
+use Mtf\Block\Form;
 use Mtf\Client\Element;
-use Mtf\Factory\Factory;
 use Mtf\Client\Element\Locator;
+use Magento\Bundle\Test\Block\Adminhtml\Catalog\Product\Edit\Tab\Bundle\Option\Selection;
+use Magento\Bundle\Test\Block\Adminhtml\Catalog\Product\Edit\Tab\Bundle\Option\Search\Grid;
 
 /**
  * Class Option
- * Bundle product options block
+ * Bundle option block on backend
  */
-class Option extends Block
+class Option extends Form
 {
     /**
-     * Grid to assign products to bundle option
+     * Selector block Grid
      *
      * @var string
      */
@@ -47,22 +48,15 @@ class Option extends Block
      *
      * @var string
      */
-    protected $selectionBlock = '#bundle_selection_row';
+    protected $selectionBlock = './/tr[contains(@id, "bundle_selection_row_")][not(@style="display: none;")][%d]';
 
     /**
-     * 'Add Products to Option' button
+     * Selector for 'Add Products to Option' button
      *
      * @var string
      */
     protected $addProducts = '[data-ui-id$=add-selection-button]';
 
-    /**
-     * Bundle option toggle
-     *
-     * @var string
-     */
-    protected $optionToggle = '[data-target$=content]';
-
     /**
      * Bundle option title
      *
@@ -71,105 +65,79 @@ class Option extends Block
     protected $title = '[name$="[title]"]';
 
     /**
-     * Bundle option type
+     * Remove selection button selector
      *
      * @var string
      */
-    protected $type = '[name$="[type]"]';
-
-    /**
-     * Determine whether bundle options is require to fill
-     *
-     * @var string
-     */
-    protected $required = '#field-option-req';
+    protected $removeSelection = 'button.delete';
 
     /**
      * Get grid for assigning products for bundle option
      *
-     * @return \Magento\Bundle\Test\Block\Adminhtml\Catalog\Product\Edit\Tab\Bundle\Option\Search\Grid
+     * @return Grid
      */
     protected function getSearchGridBlock()
     {
-        return Factory::getBlockFactory()->getMagentoBundleAdminhtmlCatalogProductEditTabBundleOptionSearchGrid(
-            $this->_rootElement->find($this->searchGridBlock, Locator::SELECTOR_XPATH)
+        return $this->blockFactory->create(
+            'Magento\Bundle\Test\Block\Adminhtml\Catalog\Product\Edit\Tab\Bundle\Option\Search\Grid',
+            ['element' => $this->_rootElement->find($this->searchGridBlock, Locator::SELECTOR_XPATH)]
         );
     }
 
     /**
      * Get product row assigned to bundle option
      *
-     * @param int $rowNumber
-     * @param Element $context
-     * @return \Magento\Bundle\Test\Block\Adminhtml\Catalog\Product\Edit\Tab\Bundle\Option\Selection
+     * @param int $rowIndex
+     * @return Selection
      */
-    protected function getSelectionBlock($rowNumber, Element $context = null)
+    protected function getSelectionBlock($rowIndex)
     {
-        $element = $context !== null ? $context : $this->_rootElement;
-        return Factory::getBlockFactory()->getMagentoBundleAdminhtmlCatalogProductEditTabBundleOptionSelection(
-            $element->find($this->selectionBlock . '_' . $rowNumber)
+        return $this->blockFactory->create(
+            'Magento\Bundle\Test\Block\Adminhtml\Catalog\Product\Edit\Tab\Bundle\Option\Selection',
+            ['element' => $this->_rootElement->find(sprintf($this->selectionBlock, $rowIndex), Locator::SELECTOR_XPATH)]
         );
     }
 
-    /**
-     * Expand block
-     *
-     * @return void
-     */
-    public function expand()
-    {
-        if (!$this->_rootElement->find($this->title)->isVisible()) {
-            $this->_rootElement->find($this->optionToggle)->click();
-        }
-    }
-
     /**
      * Fill bundle option
      *
      * @param array $fields
-     * @param Element $context
      * @return void
      *
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function fillBundleOption(array $fields, Element $context)
+    public function fillBundleOption(array $fields)
     {
-        $rowNumber = 0;
-        $this->fillOptionData($fields);
-        foreach ($fields['assigned_products'] as $field) {
-            if (is_array($field)) {
-                $this->_rootElement->find($this->addProducts)->click();
-                $searchBlock = $this->getSearchGridBlock();
-                $searchBlock->searchAndSelect($field['search_data']);
-                $searchBlock->addProducts();
-                $this->getSelectionBlock($rowNumber)->fillProductRow($field['data']);
-                $rowNumber++;
+        $mapping = $this->dataMapping($fields);
+        $this->_fill($mapping);
+        $selections = $this->_rootElement->find($this->removeSelection)->getElements();
+        if (count($selections)) {
+            foreach ($selections as $itemSelection) {
+                $itemSelection->click();
             }
         }
+        foreach ($fields['assigned_products'] as $key => $field) {
+            $this->_rootElement->find($this->addProducts)->click();
+            $searchBlock = $this->getSearchGridBlock();
+            $searchBlock->searchAndSelect($field['search_data']);
+            $searchBlock->addProducts();
+            $this->getSelectionBlock(++$key)->fillProductRow($field['data']);
+        }
     }
 
     /**
-     * Update bundle option (now only general data, skipping assignments)
-     *
-     * @param array $fields
-     * @return void
-     */
-    public function updateBundleOption(array $fields)
-    {
-        $this->fillOptionData($fields);
-    }
-
-    /**
-     * Fill in general data to bundle option
+     * Get data bundle option
      *
      * @param array $fields
-     * @return void
+     * @return array
      */
-    private function fillOptionData(array $fields)
+    public function getBundleOptionData(array $fields)
     {
-        $this->_rootElement->find($this->title)->setValue($fields['title']);
-        $this->_rootElement->find($this->type, Locator::SELECTOR_CSS, 'select')->setValue($fields['type']);
-        $this->_rootElement->find($this->required, Locator::SELECTOR_CSS, 'checkbox')
-            ->setValue($fields['required']);
+        $mapping = $this->dataMapping($fields);
+        $newField = $this->_getData($mapping);
+        foreach ($fields['assigned_products'] as $key => $field) {
+            $newField['assigned_products'][$key] = $this->getSelectionBlock($key + 1)->getProductRow($field['data']);
+        }
+        return $newField;
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b8610f0050198e422a86065c9ebde9645865d5ee
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="1">
+    <fields>
+        <title>
+            <selector>[name$="[title]"]</selector>
+            <strategy>css selector</strategy>
+        </title>
+        <type>
+            <selector>[name$='[type]']</selector>
+            <strategy>css selector</strategy>
+            <input>select</input>
+        </type>
+        <required>
+            <selector>#field-option-req</selector>
+            <strategy>css selector</strategy>
+            <input>checkbox</input>
+        </required>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option/Search/Grid.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option/Search/Grid.php
index 832a49e8d1ad93a97d266ef199df17f233551ce0..d0e2c1e280e950b1d107d60f94a9e755544b5b1f 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option/Search/Grid.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option/Search/Grid.php
@@ -24,18 +24,16 @@
 
 namespace Magento\Bundle\Test\Block\Adminhtml\Catalog\Product\Edit\Tab\Bundle\Option\Search;
 
-use Mtf\Client\Element\Locator;
 use Magento\Backend\Test\Block\Widget\Grid as GridInterface;
 
 /**
  * Class Grid
  * 'Add Products to Bundle Option' grid
- *
  */
 class Grid extends GridInterface
 {
     /**
-     * 'Add Selected Products' button
+     * Selector for 'Add Selected Products' button
      *
      * @var string
      */
@@ -49,20 +47,23 @@ class Grid extends GridInterface
     protected $selectItem = 'tbody tr .col-id';
 
     /**
-     * {@inheritdoc}
+     * Filters param for grid
+     *
+     * @var array
      */
-    protected $filters = array(
-        'name' => array(
+    protected $filters = [
+        'name' => [
             'selector' => 'input[name=name]'
-        ),
-        'sku' => array(
+        ],
+        'sku' => [
             'selector' => 'input[name=sku]'
-        ),
-    );
-
+        ],
+    ];
 
     /**
      * Press 'Add Selected Products' button
+     *
+     * @return void
      */
     public function addProducts()
     {
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option/Selection.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option/Selection.php
index fff6f222d75d7e9bbf1200b60834825a891ba827..b7f919e508747967d97502d417068191b1c2433f 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option/Selection.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option/Selection.php
@@ -24,63 +24,43 @@
 
 namespace Magento\Bundle\Test\Block\Adminhtml\Catalog\Product\Edit\Tab\Bundle\Option;
 
-use Mtf\Block\Block;
-use Mtf\Client\Element;
-use Mtf\Client\Element\Locator;
+use Mtf\Block\Form;
 
 /**
  * Class Selection
  * Assigned product row to bundle option
- *
  */
-class Selection extends Block
+class Selection extends Form
 {
     /**
-     * Fields mapping
+     * Fill data to product row
      *
-     * @var array
-     */
-    protected $mapping = array();
-
-    /**
-     * Initialize block elements
+     * @param array $fields
+     * @return void
      */
-    protected function _init()
+    public function fillProductRow(array $fields)
     {
-        $this->mapping = [
-            'selection_price_value' => [
-                'selector' => "[name$='[selection_price_value]']",
-                'type' => 'input',
-
-            ],
-            'selection_price_type' => [
-                'selector' => "[name$='[selection_price_type]']",
-                'type' => 'select',
-
-            ],
-            'selection_qty' => [
-                'selector' => "[name$='[selection_qty]']",
-                'type' => 'input',
-
-            ],
-        ];
+        unset($fields['product_id']);
+        $mapping = $this->dataMapping($fields);
+        $this->_fill($mapping);
     }
 
     /**
-     * Fill data to product row
+     * Get data item selection
      *
      * @param array $fields
+     * @return array
      */
-    public function fillProductRow(array $fields)
+    public function getProductRow(array $fields)
     {
-        foreach ($fields as $key => $value) {
-            if (isset($this->mapping[$key])) {
-                $this->_rootElement->find(
-                    $this->mapping[$key]['selector'],
-                    Locator::SELECTOR_CSS,
-                    $this->mapping[$key]['type']
-                )->setValue($value);
-            }
+        $mapping = $this->dataMapping($fields);
+        $newFields = $this->_getData($mapping);
+        if (isset($mapping['getProductName'])) {
+            $newFields['getProductName'] = $this->_rootElement->find(
+                $mapping['getProductName']['selector'],
+                $mapping['getProductName']['strategy']
+            )->getText();
         }
+        return $newFields;
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option/Selection.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option/Selection.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2c7ba5bbb41d5ced6c5036d9261e32d36bca9a9e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option/Selection.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <is_default>
+            <selector>[name$="[is_default]"]</selector>
+            <input>checkbox</input>
+        </is_default>
+        <selection_price_value>
+            <selector>[name$='[selection_price_value]']</selector>
+        </selection_price_value>
+        <selection_price_type>
+            <selector>[name$='[selection_price_type]']</selector>
+            <input>select</input>
+        </selection_price_type>
+        <selection_qty>
+            <selector>[name$='[selection_qty]']</selector>
+        </selection_qty>
+        <get_is_default>
+            <selector>[name$="[is_default]"]</selector>
+            <input>checkbox</input>
+        </get_is_default>
+        <getProductName>
+            <selector>td.col-name</selector>
+        </getProductName>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Product/ProductForm.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Product/ProductForm.xml
index 02ec36bd3bde19d9a0747dadb209ba950326471b..c1f5383c0d572fbea438b6e9d8ef0fb7de465841 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Product/ProductForm.xml
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Product/ProductForm.xml
@@ -30,6 +30,9 @@
         <strategy>css selector</strategy>
         <wrapper>product</wrapper>
         <fields>
+            <shipment_type>
+                <input>select</input>
+            </shipment_type>
             <sku_type>
                 <input>select</input>
             </sku_type>
@@ -39,9 +42,6 @@
             <weight_type>
                 <input>select</input>
             </weight_type>
-            <shipment_type>
-                <input>select</input>
-            </shipment_type>
         </fields>
     </product-details>
     <bundle>
@@ -49,4 +49,15 @@
         <selector>#product_info_tabs_product-details</selector>
         <strategy>css selector</strategy>
     </bundle>
+    <advanced-pricing>
+        <class>\Magento\Catalog\Test\Block\Adminhtml\Product\Edit\AdvancedPricingTab</class>
+        <selector>#product_info_tabs_advanced-pricing</selector>
+        <strategy>css selector</strategy>
+        <wrapper>product</wrapper>
+        <fields>
+            <price_view>
+                <input>select</input>
+            </price_view>
+        </fields>
+    </advanced-pricing>
 </tabs>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Select.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View.php
similarity index 56%
rename from dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Select.php
rename to dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View.php
index cd69d77d78d620bb8b6f5a344170be26902c9a8e..be2d98aef7ddce09e033560e067fe3034ba8dd38 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Select.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View.php
@@ -22,33 +22,35 @@
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
 
-namespace Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option;
+namespace Magento\Bundle\Test\Block\Catalog\Product;
 
-use Mtf\Block\Form;
-use Mtf\Client\Element;
 use Mtf\Client\Element\Locator;
+use Magento\Catalog\Test\Block\Product\View as ParentView;
+use Magento\Bundle\Test\Block\Catalog\Product\View\Type\Bundle;
 
 /**
- * Class Select
- * Bundle option dropdown type
- *
+ * Class View
+ * Bundle product view block on the product page
  */
-class Select extends Form
+class View extends ParentView
 {
     /**
-     * Set data in bundle option
+     * Bundle options block
      *
-     * @param array $data
+     * @var string
      */
-    public function fillOption(array $data)
-    {
-        $this->waitForElementVisible($this->mapping['value']['selector']);
+    protected $bundleBlock = '//*[@id="product-options-wrapper"]//fieldset[contains(@class,"bundle")]';
 
-        $select = $this->_rootElement->find($this->mapping['value']['selector'], Locator::SELECTOR_CSS, 'select');
-        $select->setValue($data['value']);
-        $qtyField = $this->_rootElement->find($this->mapping['qty']['selector']);
-        if (!$qtyField->isDisabled()) { //TODO should be remove after fix qty field
-            $qtyField->setValue($data['qty']);
-        }
+    /**
+     * Get bundle options block
+     *
+     * @return Bundle
+     */
+    public function getBundleBlock()
+    {
+        return $this->blockFactory->create(
+            'Magento\Bundle\Test\Block\Catalog\Product\View\Type\Bundle',
+            ['element' => $this->_rootElement->find($this->bundleBlock, Locator::SELECTOR_XPATH)]
+        );
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Bundle.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Bundle.php
index 11efcbd7f85114e2f71da9b1ed91519c10ffcb19..4e2ab8a141280a1007cc5a10a312137e7b86d89b 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Bundle.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Bundle.php
@@ -24,16 +24,98 @@
 
 namespace Magento\Bundle\Test\Block\Catalog\Product\View\Type;
 
-use Mtf\Client\Element;
-use Mtf\Factory\Factory;
-use Magento\Catalog\Test\Block\Product\View\CustomOptions;
+use Mtf\Block\Block;
+use Mtf\Client\Element\Locator;
+use Magento\Bundle\Test\Page\Product\CatalogProductView;
+use Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option;
 
 /**
  * Class Bundle
  * Catalog bundle product info block
  */
-class Bundle extends CustomOptions
+class Bundle extends Block
 {
+    /**
+     * Bundle options block
+     *
+     * @var string
+     */
+    protected $bundleBlock = './div[%d]';
+
+    /**
+     * Label item option
+     *
+     * @var string
+     */
+    protected $requiredOptions = '[%s(contains(@class,"required"))]';
+
+    /**
+     * Label item option
+     *
+     * @var string
+     */
+    protected $optionSelect = './/select/option[@value != ""][%d][contains(text(), "%s")]';
+
+    /**
+     * Label item option
+     *
+     * @var string
+     */
+    protected $optionLabel = './/div[%d][contains(@class, "field")]//*[contains(text(), "%s")]';
+
+    /**
+     * Selector DropDown type
+     *
+     * @var string
+     */
+    protected $typeDropDown = './/select[contains(@class,"bundle-option-select")]';
+
+    /**
+     * Selector Multiselect type
+     *
+     * @var string
+     */
+    protected $typeMultiple = './/select[contains(@class,"multiselect")]';
+
+    /**
+     * Selector RadioButton type
+     *
+     * @var string
+     */
+    protected $typeRadio = './/input[contains(@class,"radio")]';
+
+    /**
+     * Selector Checkbox type
+     *
+     * @var string
+     */
+    protected $typeCheckbox = './/input[contains(@class,"checkbox")]';
+
+    /**
+     * Selector bundle option block for fill
+     *
+     * @var string
+     */
+    protected $bundleOptionBlock = './/div[label[span[contains(text(), "%s")]]]';
+
+    /**
+     * Fill bundle option on frontend add click "Add to cart" button
+     *
+     * @param array $fillData
+     * @param CatalogProductView $catalogProductView
+     * @return void
+     */
+    public function addToCart(array $fillData, CatalogProductView $catalogProductView)
+    {
+        $this->fillBundleOptions($fillData['bundle_options']);
+        if (isset($fillData['custom_options'])) {
+            foreach ($fillData['custom_options'] as $option) {
+                $catalogProductView->getCustomOptionsBlock()->fillCustomOptions($option);
+            }
+        }
+        $catalogProductView->getViewBlock()->clickAddToCart();
+    }
+
     /**
      * Fill bundle options
      *
@@ -42,15 +124,74 @@ class Bundle extends CustomOptions
      */
     public function fillBundleOptions($bundleOptions)
     {
-        $index = 1;
         foreach ($bundleOptions as $option) {
-            /** @var $optionBlock \Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option\Radio|
-             * \Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option\Select */
-            $getClass = 'getMagentoBundleCatalogProductViewTypeOption' . ucfirst($option['type']);
-            $optionBlock = Factory::getBlockFactory()->$getClass(
-                $this->_rootElement->find('.field.option.required:nth-of-type(' . $index++ . ')')
+            $selector = sprintf($this->bundleOptionBlock, $option['title']);
+            /** @var Option $optionBlock */
+            $optionBlock = $this->blockFactory->create(
+                'Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option\\'
+                . $this->optionNameConvert($option['type']),
+                ['element' => $this->_rootElement->find($selector, Locator::SELECTOR_XPATH)]
             );
-            $optionBlock->fillOption($option);
+            $optionBlock->fillOption($option['value']);
+        }
+    }
+
+    /**
+     * Get bundle item option
+     *
+     * @param array $fields
+     * @param int $index
+     * @return bool|string
+     *
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     */
+    public function displayedBundleItemOption(array $fields, $index)
+    {
+        $bundleOptionBlock = $this->_rootElement->find(sprintf($this->bundleBlock, $index), Locator::SELECTOR_XPATH);
+        $option = $bundleOptionBlock->find(
+            $this->{'type' . $this->optionNameConvert($fields['type'])},
+            Locator::SELECTOR_XPATH
+        );
+        if (!$option->isVisible()) {
+            return '"' . $fields['title'] . '" Option does not equal to fixture option type.';
+        }
+
+        $formatRequired = sprintf(
+            $this->bundleBlock . $this->requiredOptions,
+            $index,
+            (($fields['required'] == 'Yes') ? '' : 'not')
+        );
+        if (!$this->_rootElement->find($formatRequired, Locator::SELECTOR_XPATH)->isVisible()) {
+            return "This Option must be " . ($fields['required'] == 'Yes') ? '' : 'not' . " required.";
+        }
+
+        foreach ($fields['assigned_products'] as $increment => $item) {
+            $isMultiAssigned = count($fields['assigned_products']) > 1;
+            $isSelectType = $fields['type'] == 'Drop-down' || $fields['type'] == 'Multiple Select';
+            $selectOptions = $isMultiAssigned && $isSelectType ? $this->optionSelect : $this->optionLabel;
+            $formatOption = sprintf($selectOptions, ++$increment, $item['name']);
+            if (!$bundleOptionBlock->find($formatOption, Locator::SELECTOR_XPATH)->isVisible()) {
+                return 'SelectOption ' . $item['name'] . ' with index '
+                . $increment . ' data is not equals with fixture SelectOption data.';
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Convert option name
+     *
+     * @param string $optionName
+     * @return string
+     */
+    protected function optionNameConvert($optionName)
+    {
+        if ($end = strpos($optionName, ' ')) {
+            $optionName = substr($optionName, 0, $end);
+        } elseif ($end = strpos($optionName, '-')) {
+            $optionName = substr($optionName, 0, $end) . ucfirst(substr($optionName, ($end + 1)));
         }
+        return $optionName;
     }
 }
diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/Discount.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option.php
similarity index 69%
rename from app/code/Magento/Tax/Model/Sales/Total/Quote/Discount.php
rename to dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option.php
index 821cc0feb06df7dcdf4825b201efa2138127b94d..10fec3f02cb790ba3ac929e6d4820e5e92dd75f9 100644
--- a/app/code/Magento/Tax/Model/Sales/Total/Quote/Discount.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option.php
@@ -18,25 +18,32 @@
  * versions in the future. If you wish to customize Magento for your
  * needs please refer to http://www.magentocommerce.com for more information.
  *
+ * @category    Mtf
+ * @package     Mtf
+ * @subpackage  functional_tests
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
 
+namespace Magento\Bundle\Test\Block\Catalog\Product\View\Type;
+
+use Mtf\Block\Form;
+
 /**
- * Tax discount totals calculation model
+ * Class Option
+ * Bundle option
  */
-namespace Magento\Tax\Model\Sales\Total\Quote;
-
-class Discount extends \Magento\Sales\Model\Quote\Address\Total\AbstractTotal
+class Option extends Form
 {
     /**
-     * Calculate discount tac amount
+     * Set data in bundle option
      *
-     * @param   \Magento\Sales\Model\Quote\Address $address
-     * @return  \Magento\Tax\Model\Sales\Total\Quote\Address
+     * @param array $data
+     * @return void
      */
-    public function collect(\Magento\Sales\Model\Quote\Address $address)
+    public function fillOption(array $data)
     {
-        //        echo 'discount';
+        $mapping = $this->dataMapping($data);
+        $this->_fill($mapping);
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Checkbox.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Checkbox.php
new file mode 100644
index 0000000000000000000000000000000000000000..a1d16d225d19a1b461d9b98e8d39f2e2cee72efc
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Checkbox.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option;
+
+/**
+ * Class Checkbox
+ * Bundle option checkbox type
+ */
+class Checkbox extends Radio
+{
+    // Parent behavior
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Checkbox.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Checkbox.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c42d667d526b959f7c7be4972e76de713b9a589b
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Checkbox.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <name>
+            <selector>.//div[label[//span[contains(text(), "%product_name%")]]]/input</selector>
+            <strategy>xpath</strategy>
+            <input>checkbox</input>
+        </name>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/Ui/CreateBundle.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/DropDown.php
similarity index 78%
rename from dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/Ui/CreateBundle.php
rename to dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/DropDown.php
index 85e35b08acbceb93f52a0f9de1e9caac7b11b021..f49b2e934e6b032367a026fe265ecdeac1277399 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/Ui/CreateBundle.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/DropDown.php
@@ -18,22 +18,19 @@
  * versions in the future. If you wish to customize Magento for your
  * needs please refer to http://www.magentocommerce.com for more information.
  *
- * @spi
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
 
-namespace Magento\Bundle\Test\Handler\Ui;
+namespace Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option;
 
-use Mtf\Fixture\FixtureInterface;
-use Mtf\Factory\Factory;
-use \Magento\Catalog\Test\Handler\Ui\CreateProduct;
+use Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option;
 
 /**
- * Class CreateBundle
- * Create a bundle product
- *
+ * Class DropDown
+ * Bundle option drop-down type
  */
-class CreateBundle extends CreateProduct
+class DropDown extends Option
 {
+    // Parent behavior
 }
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/DropDown.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/DropDown.xml
new file mode 100644
index 0000000000000000000000000000000000000000..55fa034b2d8f7bfaffbdbd49900a5fe5c29cd7c7
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/DropDown.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <name>
+            <selector>select</selector>
+            <input>select</input>
+        </name>
+        <qty>
+            <selector>//input[@class = "qty"]</selector>
+            <strategy>xpath</strategy>
+        </qty>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/CustomOptionsTab/OptionField.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Multiple.php
similarity index 77%
rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/CustomOptionsTab/OptionField.php
rename to dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Multiple.php
index a23bb8728c6225472c89222879228fedcf1a73ea..c38f846d8e8c646c38e570a95cf2541f6a4cec2e 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/CustomOptionsTab/OptionField.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Multiple.php
@@ -22,16 +22,15 @@
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
 
-namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\CustomOptionsTab;
+namespace Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option;
 
-use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Options;
+use Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option;
 
 /**
- * Class OptionField
- *
- * @package Magento\Catalog\Test\Block\Adminhtml\Product\Edit\CustomOptionsTab
+ * Class Multiple
+ * Bundle option Multiple type
  */
-class OptionField extends Options
+class Multiple extends Option
 {
     // Parent behavior
 }
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Select.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Multiple.xml
similarity index 90%
rename from dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Select.xml
rename to dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Multiple.xml
index cec08d7435696dabd950f3a69cd08fe2e7055809..53dd5f87a19bdbcbcae2ae832dea90ec09a2d3d5 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Select.xml
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Multiple.xml
@@ -25,11 +25,9 @@
 -->
 <mapping strict="0">
     <fields>
-        <value>
+        <name>
             <selector>select</selector>
-        </value>
-        <qty>
-            <selector>input.qty</selector>
-        </qty>
+            <input>multiselect</input>
+        </name>
     </fields>
 </mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Radio.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Radio.php
index 463a30caab0f16683e5aff2cbbe89137ecc6e5a1..6c44e031be0cae799a706602ba85320d76c295fb 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Radio.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Radio.php
@@ -24,25 +24,25 @@
 
 namespace Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option;
 
-use Mtf\Block\Form;
-use Mtf\Client\Element;
-use Mtf\Client\Element\Locator;
+use Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option;
 
 /**
  * Class Radio
- * Bundle option radiobutton type
- *
+ * Bundle option radio button type
  */
-class Radio extends Form
+class Radio extends Option
 {
     /**
      * Set data in bundle option
      *
      * @param array $data
+     * @return void
      */
     public function fillOption(array $data)
     {
-        $this->_rootElement->find('//*[contains(text(), ' . $data['value'] . ')]', Locator::SELECTOR_XPATH)->click();
-        $this->_rootElement->find($this->mapping['qty']['selector'])->setValue($data['qty']);
+        $mapping = $this->dataMapping($data);
+        $mapping['name']['selector'] = str_replace('%product_name%', $data['name'], $mapping['name']['selector']);
+        $mapping['name']['value'] = 'Yes';
+        $this->_fill($mapping);
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Radio.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Radio.xml
index f32831a6f725f1ae882dd1943bf7f256e7c9f769..d79a54b300f647a5c831ca635c9554c84a165755 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Radio.xml
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Radio.xml
@@ -25,8 +25,14 @@
 -->
 <mapping strict="0">
     <fields>
+        <name>
+            <selector>//div[label[//span[contains(text(), "%product_name%")]]]/input</selector>
+            <strategy>xpath</strategy>
+            <input>checkbox</input>
+        </name>
         <qty>
-            <selector>.qty-holder input</selector>
+            <selector>//input[@class = "qty"]</selector>
+            <strategy>xpath</strategy>
         </qty>
     </fields>
 </mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleInCategory.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleInCategory.php
new file mode 100644
index 0000000000000000000000000000000000000000..c12d06ca0a0f66739612e4aa1aec5561f9e67306
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleInCategory.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Test\Constraint;
+
+use Magento\Cms\Test\Page\CmsIndex;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Bundle\Test\Fixture\CatalogProductBundle;
+use Magento\Catalog\Test\Fixture\CatalogCategory;
+use Magento\Catalog\Test\Page\Category\CatalogCategoryView;
+
+/**
+ * Class AssertProductInCategory
+ */
+class AssertBundleInCategory extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Check bundle product on the category page
+     *
+     * @param CatalogCategoryView $catalogCategoryView
+     * @param CmsIndex $cmsIndex
+     * @param CatalogProductBundle $product
+     * @param CatalogCategory $category
+     * @return void
+     */
+    public function processAssert(
+        CatalogCategoryView $catalogCategoryView,
+        CmsIndex $cmsIndex,
+        CatalogProductBundle $product,
+        CatalogCategory $category
+    ) {
+        //Open category view page
+        $cmsIndex->open();
+        $cmsIndex->getTopmenu()->selectCategoryByName($category->getName());
+
+        //Process asserts
+        $this->assertPrice($product, $catalogCategoryView);
+    }
+
+    /**
+     * Verify product price on category view page
+     *
+     * @param CatalogProductBundle $bundle
+     * @param CatalogCategoryView $catalogCategoryView
+     * @return void
+     */
+    protected function assertPrice(CatalogProductBundle $bundle, CatalogCategoryView $catalogCategoryView)
+    {
+        $priceData = $bundle->getDataFieldConfig('price')['source']->getPreset();
+        //Price from/to verification
+        $priceBlock = $catalogCategoryView->getListProductBlock()->getProductPriceBlock($bundle->getName());
+
+        $priceLow = ($bundle->getPriceView() == 'Price Range')
+            ? $priceBlock->getPriceFrom()
+            : $priceBlock->getRegularPrice();
+
+        \PHPUnit_Framework_Assert::assertEquals(
+            $priceData['price_from'],
+            $priceLow,
+            'Bundle price From on category page is not correct.'
+        );
+        if ($bundle->getPriceView() == 'Price Range') {
+            \PHPUnit_Framework_Assert::assertEquals(
+                $priceData['price_to'],
+                $priceBlock->getPriceTo(),
+                'Bundle price To on category page is not correct.'
+            );
+        }
+    }
+
+    /**
+     * Text of Visible in category assert
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Bundle price on category page is not correct.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleItemsOnProductPage.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleItemsOnProductPage.php
new file mode 100644
index 0000000000000000000000000000000000000000..ec58d09f4e03f1424abb27d2492734af5295c9d1
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleItemsOnProductPage.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Bundle\Test\Fixture\CatalogProductBundle;
+use Magento\Bundle\Test\Page\Product\CatalogProductView;
+
+/**
+ * Class AssertBundleItemsOnProductPage
+ */
+class AssertBundleItemsOnProductPage extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert that displayed product bundle items data on product page equals passed from fixture preset
+     *
+     * @param CatalogProductView $catalogProductView
+     * @param CatalogProductBundle $product
+     * @return void
+     */
+    public function processAssert(CatalogProductView $catalogProductView, CatalogProductBundle $product)
+    {
+        $catalogProductView->init($product);
+        $catalogProductView->open();
+        $catalogProductView->getViewBlock()->clickCustomize();
+        $result = $this->displayedBundleBlock($catalogProductView, $product);
+        \PHPUnit_Framework_Assert::assertTrue(empty($result), $result);
+    }
+
+    /**
+     * Displayed bundle block on frontend with correct fixture product
+     *
+     * @param CatalogProductView $catalogProductView
+     * @param CatalogProductBundle $product
+     * @return string|null
+     */
+    protected function displayedBundleBlock(CatalogProductView $catalogProductView, CatalogProductBundle $product)
+    {
+        $fields = $product->getData();
+        $bundleOptions = $fields['bundle_selections']['bundle_options'];
+        if (!isset($bundleOptions)) {
+            return 'Bundle options data on product page is not equals to fixture preset.';
+        }
+
+        $catalogProductView->getViewBlock()->clickCustomize();
+        foreach ($bundleOptions as $index => $item) {
+            foreach ($item['assigned_products'] as &$selection) {
+                $selection = $selection['search_data'];
+            }
+            $result = $catalogProductView->getBundleViewBlock()->getBundleBlock()->displayedBundleItemOption(
+                $item,
+                ++$index
+            );
+
+            if ($result !== true) {
+                return $result;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return Text if displayed on frontend equals with fixture
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Bundle options data on product page equals to passed from fixture preset.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundlePriceType.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundlePriceType.php
new file mode 100644
index 0000000000000000000000000000000000000000..c05c517b04ec7e8cfc171bd391baf11db886af96
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundlePriceType.php
@@ -0,0 +1,157 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Checkout\Test\Page\CheckoutCart;
+use Magento\Bundle\Test\Fixture\CatalogProductBundle;
+use Magento\Bundle\Test\Page\Product\CatalogProductView;
+
+/**
+ * Class AssertBundlePriceType
+ */
+class AssertBundlePriceType extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Product price type
+     *
+     * @var string
+     */
+    protected $productPriceType = 'Dynamic';
+
+    /**
+     * Assert that displayed price for bundle items on shopping cart page equals to passed from fixture.
+     *   Price for bundle items has two options:
+     *   1. Fixed (price of bundle product)
+     *   2. Dynamic (price of bundle item)
+     *
+     * @param CatalogProductView $catalogProductView
+     * @param CatalogProductBundle $product
+     * @param CheckoutCart $checkoutCartView
+     * @param CatalogProductBundle $originalProduct [optional]
+     * @return void
+     */
+    public function processAssert(
+        CatalogProductView $catalogProductView,
+        CatalogProductBundle $product,
+        CheckoutCart $checkoutCartView,
+        CatalogProductBundle $originalProduct = null
+    ) {
+        $checkoutCartView->open()->getCartBlock()->clearShoppingCart();
+        //Open product view page
+        $catalogProductView->init($product);
+        $catalogProductView->open();
+
+        //Process assertions
+        $this->assertPrice($product, $catalogProductView, $checkoutCartView, $originalProduct);
+    }
+
+    /**
+     * Assert prices on the product view page and shopping cart page.
+     *
+     * @param CatalogProductBundle $product
+     * @param CatalogProductView $catalogProductView
+     * @param CheckoutCart $checkoutCartView
+     * @param CatalogProductBundle $originalProduct [optional]
+     * @return void
+     *
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     */
+    protected function assertPrice(
+        CatalogProductBundle $product,
+        CatalogProductView $catalogProductView,
+        CheckoutCart $checkoutCartView,
+        CatalogProductBundle $originalProduct = null
+    ) {
+        $customerGroup = 'NOT LOGGED IN';
+        $catalogProductView->getViewBlock()->clickCustomize();
+        $bundleData = $product->getData();
+        $this->productPriceType = $originalProduct !== null
+            ? $originalProduct->getPriceType()
+            : $product->getPriceType();
+        $fillData = $product->getDataFieldConfig('checkout_data')['source']->getPreset();
+        $bundleBlock = $catalogProductView->getBundleViewBlock()->getBundleBlock();
+        $bundleBlock->addToCart($fillData, $catalogProductView);
+        $cartBlock = $checkoutCartView->getCartBlock();
+        $specialPrice = 0;
+        if (isset($bundleData['group_price'])) {
+            $specialPrice =
+                $bundleData['group_price'][array_search($customerGroup, $bundleData['group_price'])]['price'] / 100;
+        }
+
+        $optionPrice = [];
+        foreach ($fillData['bundle_options'] as $key => $data) {
+            $subProductPrice = 0;
+            foreach ($bundleData['bundle_selections']['products'][$key] as $productKey => $itemProduct) {
+                if (strpos($itemProduct->getName(), $data['value']['name']) !== false) {
+                    $data['value']['key'] = $productKey;
+                    $subProductPrice = $itemProduct->getPrice();
+                }
+            }
+
+            $optionPrice[$key]['price'] = $this->productPriceType == 'Fixed'
+                ? number_format(
+                    $bundleData['bundle_selections']['bundle_options'][$key]['assigned_products'][$data['value']['key']]
+                    ['data']['selection_price_value'],
+                    2
+                )
+                : number_format($subProductPrice, 2);
+        }
+
+        foreach ($optionPrice as $index => $item) {
+            $item['price'] -= $item['price'] * $specialPrice;
+            \PHPUnit_Framework_Assert::assertEquals(
+                number_format($item['price'], 2),
+                $cartBlock->getPriceBundleOptions($index + 1),
+                'Bundle item ' . ($index + 1) . ' options on frontend don\'t equal to fixture.'
+            );
+        }
+        $sumOptionsPrice = $product->getDataFieldConfig('price')['source']->getPreset()['cart_price'];
+
+        $subTotal = number_format($cartBlock->getCartItemUnitPrice($product), 2);
+        \PHPUnit_Framework_Assert::assertEquals(
+            $sumOptionsPrice,
+            $subTotal,
+            'Bundle unit price on frontend doesn\'t equal to fixture.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Bundle price on shopping cart page is not correct.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundlePriceView.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundlePriceView.php
new file mode 100644
index 0000000000000000000000000000000000000000..7837398d77fc58a1ba0735dfcdb141e0329ff55f
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundlePriceView.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Bundle\Test\Page\Product\CatalogProductView;
+use Magento\Bundle\Test\Fixture\CatalogProductBundle;
+
+/**
+ * Class AssertBundlePriceView
+ */
+class AssertBundlePriceView extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert that displayed price view for bundle product on product page equals passed from fixture.
+     *
+     * @param CatalogProductView $catalogProductView
+     * @param CatalogProductBundle $product
+     * @return void
+     */
+    public function processAssert(
+        CatalogProductView $catalogProductView,
+        CatalogProductBundle $product
+    ) {
+        //Open product view page
+        $catalogProductView->init($product);
+        $catalogProductView->open();
+
+        //Process assertions
+        $this->assertPrice($product, $catalogProductView);
+    }
+
+    /**
+     * Assert prices on the product view Page
+     *
+     * @param CatalogProductBundle $product
+     * @param CatalogProductView $catalogProductView
+     * @return void
+     */
+    protected function assertPrice(CatalogProductBundle $product, CatalogProductView $catalogProductView)
+    {
+        $priceData = $product->getDataFieldConfig('price')['source']->getPreset();
+        $priceBlock = $catalogProductView->getViewBlock()->getProductPriceBlock();
+
+        $priceLow = ($product->getPriceView() == 'Price Range')
+            ? $priceBlock->getPriceFrom()
+            : $priceBlock->getRegularPrice();
+
+        \PHPUnit_Framework_Assert::assertEquals(
+            $priceData['price_from'],
+            $priceLow,
+            'Bundle price From on product view page is not correct.'
+        );
+
+        if ($product->getPriceView() == 'Price Range') {
+            \PHPUnit_Framework_Assert::assertEquals(
+                $priceData['price_to'],
+                $priceBlock->getPriceTo(),
+                'Bundle price To on product view page is not correct.'
+            );
+        }
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Bundle price on product view page is not correct.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleProductForm.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleProductForm.php
new file mode 100755
index 0000000000000000000000000000000000000000..4eff17432fefa6e3125dbd21682f1937fde8d842
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleProductForm.php
@@ -0,0 +1,133 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Test\Constraint;
+
+use Mtf\Fixture\FixtureInterface;
+use Magento\Catalog\Test\Constraint\AssertProductForm;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+
+/**
+ * Class AssertBundleProductForm
+ */
+class AssertBundleProductForm extends AssertProductForm
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Formatting options for array values
+     *
+     * @var array
+     */
+    protected $specialArray = [
+        'special_from_date' => [
+            'type' => 'date'
+        ],
+        'special_to_date' => [
+            'type' => 'date'
+        ]
+    ];
+
+    /**
+     * Assert form data equals fixture data
+     *
+     * @param FixtureInterface $product
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductEdit $productPage
+     * @return void
+     */
+    public function processAssert(
+        FixtureInterface $product,
+        CatalogProductIndex $productGrid,
+        CatalogProductEdit $productPage
+    ) {
+        $filter = ['sku' => $product->getSku()];
+        $productGrid->open();
+        $productGrid->getProductGrid()->searchAndOpen($filter);
+
+        $formData = $productPage->getForm()->getData($product);
+        $fixtureData = $this->prepareFixtureData($product->getData());
+        $errors = $this->verifyData($fixtureData, $formData);
+        \PHPUnit_Framework_Assert::assertEmpty($errors, $errors);
+    }
+
+    /**
+     * Prepares fixture data for comparison
+     *
+     * @param array $data
+     * @param array $sortFields [optional]
+     * @return array
+     */
+    protected function prepareFixtureData(array $data, array $sortFields = [])
+    {
+        $data = $this->prepareSpecialPriceArray($data);
+        $data['bundle_selections'] = $this->prepareBundleOptions(
+            $data['bundle_selections']['bundle_options']
+        );
+
+        return parent::prepareFixtureData($data, $sortFields);
+    }
+
+    /**
+     * Prepare special price array for Bundle product
+     *
+     * @param array $fields
+     * @return array
+     */
+    protected function prepareSpecialPriceArray(array $fields)
+    {
+        foreach ($this->specialArray as $key => $value) {
+            if (array_key_exists($key, $fields)) {
+                if (isset($value['type']) && $value['type'] == 'date') {
+                    $fields[$key] = vsprintf('%d/%d/%d', explode('/', $fields[$key]));
+                }
+            }
+        }
+        return $fields;
+    }
+
+    /**
+     * Prepare Bundle Options array from preset
+     *
+     * @param array $bundleSelections
+     * @return array
+     */
+    protected function prepareBundleOptions(array $bundleSelections)
+    {
+        foreach ($bundleSelections as &$item) {
+            foreach ($item['assigned_products'] as &$selection) {
+                $selection['data']['getProductName'] = $selection['search_data']['name'];
+                $selection = $selection['data'];
+            }
+        }
+
+        return $bundleSelections;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleProductPage.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleProductPage.php
new file mode 100644
index 0000000000000000000000000000000000000000..874df95f117b3b8d1cce4699d1b93c8796d642cf
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleProductPage.php
@@ -0,0 +1,90 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Test\Constraint;
+
+use Magento\Catalog\Test\Constraint\AssertProductPage;
+
+/**
+ * Class AssertBundleProductPage
+ */
+class AssertBundleProductPage extends AssertProductPage
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Error messages
+     *
+     * @var array
+     */
+    protected $errorsMessages = [
+        'name' => '- product name on product view page is not correct.',
+        'sku' => '- product sku on product view page is not correct.',
+        'price_from' => '- bundle product price from on product view page is not correct.',
+        'price_to' => '- bundle product price to on product view page is not correct.',
+        'short_description' => '- product short description on product view page is not correct.',
+        'description' => '- product description on product view page is not correct.'
+    ];
+
+    /**
+     * Prepare Price data
+     *
+     * @param array $price
+     * @return array
+     */
+    protected function preparePrice($price)
+    {
+        $priceData = $this->product->getDataFieldConfig('price')['source']->getPreset();
+        $priceView = $this->product->getPriceView();
+        if ($priceView === null || $priceView == 'Price Range') {
+            if (isset($price['price_from']) && isset($price['price_to'])) {
+                return [
+                    ['price_from' => $price['price_from'], 'price_to' => $price['price_to']],
+                    [
+                        'price_from' => number_format($priceData['price_from'], 2),
+                        'price_to' => number_format($priceData['price_to'], 2)
+                    ]
+                ];
+            }
+            return [
+                ['price_regular_price' => $price['price_regular_price']],
+                ['price_regular_price' => number_format($priceData['price_from'], 2)]
+            ];
+        } else {
+            return [
+                ['price_from' => $price['price_regular_price']],
+                [
+                    'price_from' => is_numeric($priceData['price_from'])
+                            ? number_format($priceData['price_from'], 2)
+                            : $priceData['price_from']
+                ]
+            ];
+        }
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertGroupedPriceOnBundleProductPage.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertGroupedPriceOnBundleProductPage.php
new file mode 100644
index 0000000000000000000000000000000000000000..1b2369329c2b5eb46ac8d8edf80a89d15cf5b05d
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertGroupedPriceOnBundleProductPage.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Test\Constraint;
+
+use Mtf\Fixture\FixtureInterface;
+use Magento\Catalog\Test\Block\Product\View;
+use Magento\Catalog\Test\Constraint\AssertProductGroupedPriceOnProductPage;
+
+/**
+ * Class AssertGroupedPriceOnBundleProductPage
+ */
+class AssertGroupedPriceOnBundleProductPage extends AssertProductGroupedPriceOnProductPage
+{
+    /**
+     * Get grouped price with fixture product and product page
+     *
+     * @param View $view
+     * @param FixtureInterface $product
+     * @return array
+     */
+    protected function getGroupedPrice(View $view, FixtureInterface $product)
+    {
+        $groupPrice['onPage'] = $view->getProductPrice();
+        $groupPrice['onPage'] = isset($groupPrice['onPage']['price_regular_price'])
+            ? str_replace('As low as $', '', $groupPrice['onPage']['price_regular_price'])
+            : str_replace('$', '', $groupPrice['onPage']['price_from']);
+        $groupPrice['fixture'] = $product->getDataFieldConfig('price')['source']->getPreset()['price_from'];
+
+        return $groupPrice;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertTierPriceOnBundleProductPage.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertTierPriceOnBundleProductPage.php
new file mode 100644
index 0000000000000000000000000000000000000000..2c83ca887ef77e74bcd1816352754d741c5076ee
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertTierPriceOnBundleProductPage.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Test\Constraint;
+
+use Mtf\Fixture\FixtureInterface;
+use Magento\Catalog\Test\Page\Product\CatalogProductView;
+use Magento\Catalog\Test\Constraint\AssertProductTierPriceOnProductPage;
+
+/**
+ * Class AssertTierPriceOnBundleProductPage
+ */
+class AssertTierPriceOnBundleProductPage extends AssertProductTierPriceOnProductPage
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Tier price block
+     *
+     * @var string
+     */
+    protected $tierBlock = '.prices.tier.items';
+
+    /**
+     * Decimals for price format
+     *
+     * @var int
+     */
+    protected $priceFormat = 4;
+
+    /**
+     * Assertion that tier prices are displayed correctly
+     *
+     * @param CatalogProductView $catalogProductView
+     * @param FixtureInterface $product
+     * @return void
+     */
+    public function processAssert(CatalogProductView $catalogProductView, FixtureInterface $product)
+    {
+        //Open product view page
+        $catalogProductView->init($product);
+        $catalogProductView->open();
+        $viewBlock = $catalogProductView->getViewBlock();
+        $viewBlock->clickCustomize();
+
+        //Process assertions
+        $this->assertPrice($product, $catalogProductView);
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Bundle.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Bundle.php
index c2633656f9f80249a60a691f378437aa83a043ba..a6f6acd904439dd74e6018c326d3c52e7e92aabd 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Bundle.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Bundle.php
@@ -114,18 +114,16 @@ class Bundle extends Product
      */
     public function getSelectionData()
     {
-        $typeMapping = [
-            'Drop-down' => 'select'
-        ];
         $options = $this->getData('checkout/selection');
         $selectionData = [];
         foreach ($options as $option => $selection) {
             $fieldPrefix = 'fields/bundle_selections/value/bundle_options/';
-            $selectionItem['type'] = $typeMapping[$this->getData($fieldPrefix . $option . '/type')];
-            $selectionItem['qty'] = $this->getData(
+            $selectionItem['type'] = $this->getData($fieldPrefix . $option . '/type');
+            $selectionItem['title'] = $this->getData($fieldPrefix . $option . '/title');
+            $selectionItem['value']['qty'] = $this->getData(
                 $fieldPrefix . $option . '/assigned_products/' . $selection . '/data/selection_qty'
             );
-            $selectionItem['value'] = $this->getData(
+            $selectionItem['value']['name'] = $this->getData(
                 $fieldPrefix . $option . '/assigned_products/' . $selection . '/search_data/name'
             );
             $selectionData[] = $selectionItem;
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleDynamic.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleDynamic.php
index 9e05a48b88dd6334f898ff9959e821f9d0204f85..f66686255f80f46f01f457e9852da4e81362a1e9 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleDynamic.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleDynamic.php
@@ -28,6 +28,7 @@ use Mtf\Factory\Factory;
 
 /**
  * Class BundleDynamic
+ * Fixture for Bundle dynamic
  */
 class BundleDynamic extends Bundle
 {
@@ -36,83 +37,81 @@ class BundleDynamic extends Bundle
      */
     protected function _initData()
     {
-        $this->_data['checkout'] = array(
-            'prices' => array(
+        $this->_data['checkout'] = [
+            'prices' => [
                 'price_from' => 10,
                 'price_to' => 15
-            ),
-            'selection' => array(
-                'bundle_item_0' => 'assigned_product_0'
-            )
-        );
+            ],
+            'selection' => [0]
+        ];
         parent::_initData();
         $this->_data['fields'] = array_merge_recursive(
             $this->_data['fields'],
-            array(
-                'sku_type' => array(
+            [
+                'sku_type' => [
                     'value' => 'Dynamic',
                     'input_value' => '0',
                     'group' => static::GROUP_PRODUCT_DETAILS,
                     'input' => 'select'
-                ),
-                'price_type' => array(
+                ],
+                'price_type' => [
                     'value' => 'Dynamic',
                     'input_value' => '0',
                     'group' => static::GROUP_PRODUCT_DETAILS,
                     'input' => 'select'
-                ),
-                'weight_type' => array(
+                ],
+                'weight_type' => [
                     'value' => 'Dynamic',
                     'input_value' => '0',
                     'group' => static::GROUP_PRODUCT_DETAILS,
                     'input' => 'select'
-                ),
-                'product_website_1' => array(
+                ],
+                'product_website_1' => [
                     'value' => 'Yes',
-                    'input_value' => array(1),
+                    'input_value' => [1],
                     'group' => static::GROUP_PRODUCT_WEBSITE,
                     'input' => 'checkbox',
                     'input_name' => 'website_ids'
-                ),
-                'shipment_type' => array(
+                ],
+                'shipment_type' => [
                     'value' => 'Separately',
                     'input_value' => '1',
                     'group' => static::GROUP_PRODUCT_DETAILS,
                     'input' => 'select'
-                ),
-                'bundle_selections' => array(
-                    'value' => array(
-                        'bundle_options' => array(
-                            'bundle_item_0' => array(
+                ],
+                'bundle_selections' => [
+                    'value' => [
+                        'bundle_options' => [
+                            [
                                 'title' => 'Drop-down Option',
                                 'type' => 'Drop-down',
                                 'required' => 'Yes',
-                                'assigned_products' => array(
-                                    'assigned_product_0' => array(
-                                        'search_data' => array(
+                                'assigned_products' => [
+                                    [
+                                        'search_data' => [
                                             'name' => '%item1_simple1::getName%',
-                                        ),
-                                        'data' => array(
+                                        ],
+                                        'data' => [
                                             'selection_qty' => 1,
                                             'product_id' => '%item1_simple1::getProductId%'
-                                        )
-                                    ),
-                                    'assigned_product_1' => array(
-                                        'search_data' => array(
+                                        ]
+                                    ],
+                                    [
+                                        'search_data' => [
                                             'name' => '%item1_virtual2::getName%',
-                                        ),
-                                        'data' => array(
+                                        ],
+                                        'data' => [
                                             'selection_qty' => 1,
                                             'product_id' => '%item1_virtual2::getProductId%'
-                                        )
-                                    )
-                                )
-                            )
-                        )
-                    ),
+                                        ]
+                                    ]
+                                ]
+                            ]
+                        ]
+                    ],
                     'group' => static::GROUP
-                )
-            )
+                ]
+            ]
         );
         $this->_repository = Factory::getRepositoryFactory()
             ->getMagentoBundleBundle($this->_dataConfig, $this->_data);
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleFixed.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleFixed.php
index 7ec001adb6b9f1efca08d23a3e0d93462e79e96c..395ae740ead8da6b14aeb3b8628c705d632ece9c 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleFixed.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleFixed.php
@@ -28,6 +28,7 @@ use Mtf\Factory\Factory;
 
 /**
  * Class BundleFixed
+ * Fixture for Bundle fixed
  */
 class BundleFixed extends Bundle
 {
@@ -38,101 +39,99 @@ class BundleFixed extends Bundle
      */
     protected function _initData()
     {
-        $this->_data['checkout'] = array(
-            'prices' => array(
+        $this->_data['checkout'] = [
+            'prices' => [
                 'price_from' => 110,
                 'price_to' => 120
-            ),
-            'selection' => array(
-                'bundle_item_0' => 'assigned_product_0'
-            )
-        );
+            ],
+            'selection' => [0]
+        ];
         parent::_initData();
         $this->_data['fields'] = array_merge_recursive(
             $this->_data['fields'],
-            array(
-                'sku_type' => array(
+            [
+                'sku_type' => [
                     'value' => 'Fixed',
                     'input_value' => '1',
                     'group' => static::GROUP_PRODUCT_DETAILS,
                     'input' => 'select'
-                ),
-                'price_type' => array(
+                ],
+                'price_type' => [
                     'value' => 'Fixed',
                     'input_value' => '1',
                     'group' => static::GROUP_PRODUCT_DETAILS,
                     'input' => 'select'
-                ),
-                'price' => array(
+                ],
+                'price' => [
                     'value' => 100,
                     'group' => static::GROUP_PRODUCT_DETAILS
-                ),
-                'tax_class_id' => array(
+                ],
+                'tax_class_id' => [
                     'value' => 'Taxable Goods',
                     'input_value' => '2',
                     'group' => static::GROUP_PRODUCT_DETAILS,
                     'input' => 'select'
-                ),
-                'weight_type' => array(
+                ],
+                'weight_type' => [
                     'value' => 'Fixed',
                     'input_value' => '1',
                     'group' => static::GROUP_PRODUCT_DETAILS,
                     'input' => 'select'
-                ),
-                'weight' => array(
+                ],
+                'weight' => [
                     'value' => '1',
                     'group' => static::GROUP_PRODUCT_DETAILS
-                ),
-                'product_website_1' => array(
+                ],
+                'product_website_1' => [
                     'value' => 'Yes',
-                    'input_value' => array(1),
+                    'input_value' => [1],
                     'group' => static::GROUP_PRODUCT_WEBSITE,
                     'input' => 'checkbox',
                     'input_name' => 'website_ids'
-                ),
-                'shipment_type' => array(
+                ],
+                'shipment_type' => [
                     'value' => 'Separately',
                     'input_value' => '1',
                     'group' => static::GROUP_PRODUCT_DETAILS,
                     'input' => 'select'
-                ),
-                'bundle_selections' => array(
-                    'value' => array(
-                        'bundle_options' => array(
-                            'bundle_item_0' => array(
+                ],
+                'bundle_selections' => [
+                    'value' => [
+                        'bundle_options' => [
+                            [
                                 'title' => 'Drop-down Option',
                                 'type' => 'Drop-down',
                                 'required' => 'Yes',
-                                'assigned_products' => array(
-                                    'assigned_product_0' => array(
-                                        'search_data' => array(
+                                'assigned_products' => [
+                                    [
+                                        'search_data' => [
                                             'name' => '%item1_simple1::getName%',
-                                        ),
-                                        'data' => array(
+                                        ],
+                                        'data' => [
                                             'selection_price_value' => 10,
                                             'selection_price_type' => 'Fixed',
                                             'selection_qty' => 1,
                                             'product_id' => '%item1_simple1::getProductId%'
-                                        )
-                                    ),
-                                    'assigned_product_1' => array(
-                                        'search_data' => array(
+                                        ]
+                                    ],
+                                    [
+                                        'search_data' => [
                                             'name' => '%item1_virtual2::getName%',
-                                        ),
-                                        'data' => array(
+                                        ],
+                                        'data' => [
                                             'selection_price_value' => 20,
                                             'selection_price_type' => 'Percent',
                                             'selection_qty' => 1,
                                             'product_id' => '%item1_virtual2::getProductId%'
-                                        )
-                                    )
-                                )
-                            )
-                        )
-                    ),
+                                        ]
+                                    ]
+                                ]
+                            ]
+                        ]
+                    ],
                     'group' => static::GROUP
-                )
-            )
+                ]
+            ]
         );
         $this->_repository = Factory::getRepositoryFactory()
             ->getMagentoBundleBundle($this->_dataConfig, $this->_data);
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle.php
index bf03465b8c63fe7da2414982572ac0d779538907..2b1819dab070cea1788a9332845fd5e07b056227 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle.php
@@ -36,7 +36,7 @@ use Mtf\System\Event\EventManagerInterface;
  * Fixture for Bundle product
  *
  * @SuppressWarnings(PHPMD.ExcessivePublicCount)
- * @SuppressWarnings(PHPMD.TooManyFields) 
+ * @SuppressWarnings(PHPMD.TooManyFields)
  */
 class CatalogProductBundle extends InjectableFixture
 {
@@ -109,6 +109,7 @@ class CatalogProductBundle extends InjectableFixture
         'is_required' => '0',
         'default_value' => '',
         'input' => 'text',
+        'group' => 'product-details',
         'source' => 'Magento\Catalog\Test\Fixture\CatalogProductSimple\CategoryIds',
     ];
 
@@ -616,6 +617,13 @@ class CatalogProductBundle extends InjectableFixture
         'source' => 'Magento\Bundle\Test\Fixture\CatalogProductBundle\BundleSelections',
     ];
 
+    protected $checkout_data = [
+        'attribute_code' => 'checkout_data',
+        'backend_type' => 'virtual',
+        'is_required' => '1',
+        'source' => 'Magento\Bundle\Test\Fixture\CatalogProductBundle\CheckoutData',
+    ];
+
     protected $custom_options = [
         'attribute_code' => 'custom_options',
         'backend_type' => 'virtual',
@@ -633,15 +641,20 @@ class CatalogProductBundle extends InjectableFixture
     ];
 
     protected $stock_data = [
-        'attribute_code' => 'stock_data'
+        'attribute_code' => 'stock_data',
+        'group' => 'advanced-inventory'
     ];
 
     protected $category_id = [
-        'attribute_code' => 'category_id'
+        'attribute_code' => 'category_id',
+        'group' => 'product-details'
     ];
 
     protected $website_ids = [
-        'attribute_code' => 'website_ids'
+        'attribute_code' => 'website_ids',
+        'backend_type' => 'virtual',
+        'default_value' => ['Main Website'],
+        'group' => 'websites',
     ];
 
     public function getCategoryIds()
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle.xml
index 21874f301c9e4fd06e7e01a5dda024559cb1cd0b..3400eb8faf2c9a78da9db8483bc7801665d18972 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle.xml
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle.xml
@@ -429,7 +429,7 @@
             <backend_type>virtual</backend_type>
             <is_required>1</is_required>
             <group>bundle</group>
-            <source>Magento\Bundle\Test\Fixture\CatalogProductBundle\BundleSelections</source>
+            <fixture>Magento\Bundle\Test\Fixture\Bundle\BundleSelections</fixture>
         </bundle_selections>
         <custom_options>
             <attribute_code>custom_options</attribute_code>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle/BundleSelections.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle/BundleSelections.php
index d0bb920f995d63aab6d1274acd55084a231a6467..3a48675641374a0869570e5f34211c9790e37296 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle/BundleSelections.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle/BundleSelections.php
@@ -26,11 +26,10 @@ namespace Magento\Bundle\Test\Fixture\CatalogProductBundle;
 
 use Mtf\Fixture\FixtureFactory;
 use Mtf\Fixture\FixtureInterface;
-use Mtf\Fixture\InjectableFixture;
 
 /**
  * Class BundleSelections
- * "Selections" for the bundle product
+ * Bundle selections preset
  */
 class BundleSelections implements FixtureInterface
 {
@@ -56,12 +55,12 @@ class BundleSelections implements FixtureInterface
     protected $currentPreset;
 
     /**
-     * "Selections" source constructor
+     * Constructor
      *
+     * @constructor
      * @param FixtureFactory $fixtureFactory
      * @param array $data
      * @param array $params [optional]
-     * @throws \Exception
      */
     public function __construct(FixtureFactory $fixtureFactory, array $data, array $params = [])
     {
@@ -72,39 +71,32 @@ class BundleSelections implements FixtureInterface
             $this->data = $this->getPreset($this->currentPreset);
             if (!empty($data['products'])) {
                 $this->data['products'] = [];
-                $this->data['products'][] = explode(',', $data['products']);
+                $this->data['products'] = explode('|', $data['products']);
+                foreach ($this->data['products'] as $key => $products) {
+                    $this->data['products'][$key] = explode(',', $products);
+                }
             }
         }
 
         if (!empty($this->data['products'])) {
             $productsSelections = $this->data['products'];
             $this->data['products'] = [];
-            foreach ($productsSelections as $products) {
+            foreach ($productsSelections as $index => $products) {
                 $productSelection = [];
-                foreach ($products as $product) {
+                foreach ($products as $key => $product) {
                     list($fixture, $dataSet) = explode('::', $product);
-                    /** @var $productFixture InjectableFixture */
-                    $productFixture = $fixtureFactory->createByCode($fixture, ['dataSet' => $dataSet]);
-                    if (!$productFixture->hasData('id')) {
-                        $productFixture->persist();
-                    }
-                    $productSelection[] = $productFixture;
+                    $productSelection[$key] = $fixtureFactory->createByCode($fixture, ['dataSet' => $dataSet]);
+                    $productSelection[$key]->persist();
+                    $this->data['bundle_options'][$index]['assigned_products'][$key]['search_data']['name'] =
+                        $productSelection[$key]->getName();
                 }
                 $this->data['products'][] = $productSelection;
             }
-
-            foreach ($this->data['bundle_options'] as $optionKey => &$bundleOption) {
-                foreach ($bundleOption['assigned_products'] as $productKey => &$assignedProducts) {
-                    $assignedProducts['search_data']['name'] = $this->data['products'][$optionKey][$productKey]
-                        ->getName();
-                }
-                unset($bundleOption, $assignedProducts);
-            }
         }
     }
 
     /**
-     * Persists prepared data into application
+     * Persist bundle selections products
      *
      * @return void
      */
@@ -113,43 +105,10 @@ class BundleSelections implements FixtureInterface
         //
     }
 
-    /**
-     * Get selection for performing checkout
-     *
-     * @return array|null
-     */
-    public function getSelectionForCheckout()
-    {
-        /** @var \Magento\Catalog\Test\Fixture\CatalogProductSimple $product */
-        $product = reset($this->data['products'])[0];
-        $selectionsForCheckout = [
-            'default' => [
-                0 => [
-                    'value' => $product->getName(),
-                    'type' => 'select',
-                    'qty' => 1
-                ]
-            ],
-            'second' => [
-                0 => [
-                    'value' => $product->getName(),
-                    'type' => 'select',
-                    'qty' => 1
-                ]
-            ],
-        ];
-
-        if (!isset($selectionsForCheckout[$this->currentPreset])) {
-            return null;
-        }
-
-        return $selectionsForCheckout[$this->currentPreset];
-    }
-
     /**
      * Return prepared data set
      *
-     * @param string|null $key [optional]
+     * @param string $key [optional]
      * @return mixed
      *
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
@@ -170,7 +129,7 @@ class BundleSelections implements FixtureInterface
     }
 
     /**
-     * Getting preset data
+     * Preset array
      *
      * @param string $name
      * @return mixed
@@ -181,7 +140,7 @@ class BundleSelections implements FixtureInterface
     protected function getPreset($name)
     {
         $presets = [
-            'default' => [
+            'default_dynamic' => [
                 'bundle_options' => [
                     [
                         'title' => 'Drop-down Option',
@@ -210,11 +169,11 @@ class BundleSelections implements FixtureInterface
                 'products' => [
                     [
                         'catalogProductSimple::default',
-                        'catalogProductSimple::default'
+                        'catalogProductSimple::100_dollar_product'
                     ]
                 ]
             ],
-            'default_dynamic' => [
+            'default_fixed' => [
                 'bundle_options' => [
                     [
                         'title' => 'Drop-down Option',
@@ -226,6 +185,8 @@ class BundleSelections implements FixtureInterface
                                     'name' => '%product_name%'
                                 ],
                                 'data' => [
+                                    'selection_price_value' => 5.00,
+                                    'selection_price_type' => 'Fixed',
                                     'selection_qty' => 1,
                                 ]
                             ],
@@ -234,6 +195,8 @@ class BundleSelections implements FixtureInterface
                                     'name' => '%product_name%'
                                 ],
                                 'data' => [
+                                    'selection_price_value' => 6.00,
+                                    'selection_price_type' => 'Fixed',
                                     'selection_qty' => 1,
                                 ]
                             ]
@@ -243,11 +206,11 @@ class BundleSelections implements FixtureInterface
                 'products' => [
                     [
                         'catalogProductSimple::default',
-                        'catalogProductSimple::default'
-                    ]
+                        'catalogProductSimple::100_dollar_product'
+                    ],
                 ]
             ],
-            'default_fixed' => [
+            'second' => [
                 'bundle_options' => [
                     [
                         'title' => 'Drop-down Option',
@@ -262,7 +225,6 @@ class BundleSelections implements FixtureInterface
                                     'selection_price_value' => 5.00,
                                     'selection_price_type' => 'Fixed',
                                     'selection_qty' => 1,
-                                    'selection_can_change_qty' => 'Yes',
                                 ]
                             ],
                             [
@@ -270,10 +232,9 @@ class BundleSelections implements FixtureInterface
                                     'name' => '%product_name%'
                                 ],
                                 'data' => [
-                                    'selection_price_value' => 5.00,
+                                    'selection_price_value' => 10.00,
                                     'selection_price_type' => 'Fixed',
                                     'selection_qty' => 1,
-                                    'selection_can_change_qty' => 'Yes',
                                 ]
                             ]
                         ]
@@ -282,11 +243,11 @@ class BundleSelections implements FixtureInterface
                 'products' => [
                     [
                         'catalogProductSimple::default',
-                        'catalogProductSimple::default'
-                    ]
+                        'catalogProductSimple::100_dollar_product'
+                    ],
                 ]
             ],
-            'second' => [
+            'all_types_fixed' => [
                 'bundle_options' => [
                     [
                         'title' => 'Drop-down Option',
@@ -301,7 +262,6 @@ class BundleSelections implements FixtureInterface
                                     'selection_price_value' => 5.00,
                                     'selection_price_type' => 'Fixed',
                                     'selection_qty' => 1,
-                                    'selection_can_change_qty' => 'Yes',
                                 ]
                             ],
                             [
@@ -309,10 +269,90 @@ class BundleSelections implements FixtureInterface
                                     'name' => '%product_name%'
                                 ],
                                 'data' => [
-                                    'selection_price_value' => 10.00,
+                                    'selection_price_value' => 6.00,
+                                    'selection_price_type' => 'Fixed',
+                                    'selection_qty' => 1,
+                                ]
+                            ]
+                        ]
+                    ],
+                    [
+                        'title' => 'Radio Button Option',
+                        'type' => 'Radio Buttons',
+                        'required' => 'Yes',
+                        'assigned_products' => [
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_price_value' => 5.00,
+                                    'selection_price_type' => 'Fixed',
+                                    'selection_qty' => 1,
+                                ]
+                            ],
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_price_value' => 6.00,
+                                    'selection_price_type' => 'Fixed',
+                                    'selection_qty' => 1,
+                                ]
+                            ]
+                        ]
+                    ],
+                    [
+                        'title' => 'Checkbox Option',
+                        'type' => 'Checkbox',
+                        'required' => 'Yes',
+                        'assigned_products' => [
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_price_value' => 5.00,
+                                    'selection_price_type' => 'Fixed',
+                                    'selection_qty' => 1,
+                                ]
+                            ],
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_price_value' => 6.00,
+                                    'selection_price_type' => 'Fixed',
+                                    'selection_qty' => 1,
+                                ]
+                            ]
+                        ]
+                    ],
+                    [
+                        'title' => 'Multiple Select Option',
+                        'type' => 'Multiple Select',
+                        'required' => 'Yes',
+                        'assigned_products' => [
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_price_value' => 5.00,
+                                    'selection_price_type' => 'Fixed',
+                                    'selection_qty' => 1,
+                                ]
+                            ],
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_price_value' => 6.00,
                                     'selection_price_type' => 'Fixed',
                                     'selection_qty' => 1,
-                                    'selection_can_change_qty' => 'Yes',
                                 ]
                             ]
                         ]
@@ -321,18 +361,210 @@ class BundleSelections implements FixtureInterface
                 'products' => [
                     [
                         'catalogProductSimple::default',
-                        'catalogProductSimple::default'
+                        'catalogProductSimple::100_dollar_product'
+                    ],
+                    [
+                        'catalogProductSimple::default',
+                        'catalogProductSimple::100_dollar_product'
+                    ],
+                    [
+                        'catalogProductSimple::default',
+                        'catalogProductSimple::100_dollar_product'
+                    ],
+                    [
+                        'catalogProductSimple::default',
+                        'catalogProductSimple::100_dollar_product'
+                    ],
+                ]
+            ],
+            'all_types_dynamic' => [
+                'bundle_options' => [
+                    [
+                        'title' => 'Drop-down Option',
+                        'type' => 'Drop-down',
+                        'required' => 'Yes',
+                        'assigned_products' => [
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_qty' => 1,
+                                ]
+                            ],
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_qty' => 1,
+                                ]
+                            ]
+                        ]
+                    ],
+                    [
+                        'title' => 'Radio Button Option',
+                        'type' => 'Radio Buttons',
+                        'required' => 'Yes',
+                        'assigned_products' => [
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_qty' => 1,
+                                ]
+                            ],
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_qty' => 1,
+                                ]
+                            ]
+                        ]
+                    ],
+                    [
+                        'title' => 'Checkbox Option',
+                        'type' => 'Checkbox',
+                        'required' => 'Yes',
+                        'assigned_products' => [
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_qty' => 1,
+                                ]
+                            ],
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_qty' => 1,
+                                ]
+                            ]
+                        ]
+                    ],
+                    [
+                        'title' => 'Multiple Select Option',
+                        'type' => 'Multiple Select',
+                        'required' => 'Yes',
+                        'assigned_products' => [
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_qty' => 1,
+                                ]
+                            ],
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_qty' => 1,
+                                ]
+                            ]
+                        ]
+                    ],
+                ],
+                'products' => [
+                    [
+                        'catalogProductSimple::default',
+                        'catalogProductSimple::100_dollar_product'
+                    ],
+                    [
+                        'catalogProductSimple::default',
+                        'catalogProductSimple::100_dollar_product'
+                    ],
+                    [
+                        'catalogProductSimple::default',
+                        'catalogProductSimple::100_dollar_product'
+                    ],
+                    [
+                        'catalogProductSimple::default',
+                        'catalogProductSimple::100_dollar_product'
+                    ],
+                ]
+            ],
+            'with_not_required_options' => [
+                'bundle_options' => [
+                    [
+                        'title' => 'Drop-down Option',
+                        'type' => 'Drop-down',
+                        'required' => 'No',
+                        'assigned_products' => [
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_qty' => 1,
+                                    'selection_price_value' => 45,
+                                    'selection_price_type' => 'Fixed',
+                                ]
+                            ],
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_qty' => 1,
+                                    'selection_price_value' => 43,
+                                    'selection_price_type' => 'Fixed',
+                                ]
+                            ]
+                        ]
+                    ],
+                    [
+                        'title' => 'Radio Button Option',
+                        'type' => 'Radio Buttons',
+                        'required' => 'No',
+                        'assigned_products' => [
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_qty' => 1,
+                                    'selection_price_value' => 45,
+                                    'selection_price_type' => 'Fixed',
+                                ]
+                            ],
+                            [
+                                'search_data' => [
+                                    'name' => '%product_name%'
+                                ],
+                                'data' => [
+                                    'selection_qty' => 1,
+                                    'selection_price_value' => 43,
+                                    'selection_price_type' => 'Fixed',
+                                ]
+                            ]
+                        ]
+                    ],
+                ],
+                'products' => [
+                    [
+                        'catalogProductSimple::default',
+                        'catalogProductSimple::100_dollar_product'
+                    ],
+                    [
+                        'catalogProductSimple::default',
+                        'catalogProductSimple::100_dollar_product'
                     ]
                 ]
-            ]
+            ],
         ];
-
         if (!isset($presets[$name])) {
             throw new \InvalidArgumentException(
                 sprintf('Wrong Bundle Selections preset name: %s', $name)
             );
         }
-
         return $presets[$name];
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle/CheckoutData.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle/CheckoutData.php
new file mode 100644
index 0000000000000000000000000000000000000000..fcd9289437fe862e59ac68713f265fc2efb0e736
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle/CheckoutData.php
@@ -0,0 +1,228 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Test\Fixture\CatalogProductBundle;
+
+use Magento\Catalog\Test\Fixture\CatalogProductSimple\CheckoutData as AbstractCheckoutData;
+
+/**
+ * Class CheckoutData
+ * Data keys:
+ *  - preset (Checkout data verification preset name)
+ *
+ * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+ */
+class CheckoutData extends AbstractCheckoutData
+{
+    /**
+     * Get preset array
+     *
+     * @return array|null
+     */
+    public function getPreset()
+    {
+        $presets = [
+            'default' => [
+                'bundle_options' => [
+                    [
+                        'title' => 'Drop-down Option',
+                        'type' => 'Drop-down',
+                        'value' => [
+                            'name' => '100_dollar_product'
+                        ]
+                    ],
+                ],
+            ],
+            'with_not_required_options' => [
+                'bundle_options' => [
+                    [
+                        'title' => 'Drop-down Option',
+                        'type' => 'Drop-down',
+                        'value' => [
+                            'name' => '100_dollar_product'
+                        ]
+                    ],
+                    [
+                        'title' => 'Radio Button Option',
+                        'type' => 'Radio Buttons',
+                        'value' => [
+                            'name' => '100_dollar_product'
+                        ]
+                    ],
+                ],
+            ],
+            'with_custom_options_1' => [
+                'bundle_options' => [
+                    [
+                        'title' => 'Drop-down Option',
+                        'type' => 'Drop-down',
+                        'value' => [
+                            'name' => '100_dollar_product'
+                        ]
+                    ],
+                ],
+                'custom_options' => [
+                    [
+                        'type' => 'Drop-down',
+                        'title' => 'custom option drop down',
+                        'value' => ['30 bucks'],
+                    ],
+                ]
+            ],
+            'with_custom_options_2' => [
+                'bundle_options' => [
+                    [
+                        'title' => 'Drop-down Option',
+                        'type' => 'Drop-down',
+                        'value' => [
+                            'name' => '100_dollar_product'
+                        ]
+                    ],
+                ],
+                'custom_options' => [
+                    [
+                        'type' => 'Drop-down',
+                        'title' => 'custom option drop down',
+                        'value' => ['10 percent'],
+                    ],
+                ]
+            ],
+            'all_types_bundle_fixed_and_custom_options' => [
+                'bundle_options' => [
+                    [
+                        'title' => 'Drop-down Option',
+                        'type' => 'Drop-down',
+                        'value' => [
+                            'name' => '100_dollar_product'
+                        ]
+                    ],
+                    [
+                        'title' => 'Radio Button Option',
+                        'type' => 'Radio Buttons',
+                        'value' => [
+                            'name' => '100_dollar_product'
+                        ]
+                    ],
+                    [
+                        'title' => 'Checkbox Option',
+                        'type' => 'Checkbox',
+                        'value' => [
+                            'name' => '100_dollar_product'
+                        ]
+                    ],
+                    [
+                        'title' => 'Multiple Select Option',
+                        'type' => 'Multiple',
+                        'value' => [
+                            'name' => '100_dollar_product'
+                        ]
+                    ],
+                ],
+                'custom_options' => [
+                    [
+                        'type' => 'Field',
+                        'title' => 'custom option field',
+                        'value' => ['Field'],
+                    ],
+                    [
+                        'type' => 'Area',
+                        'title' => 'custom option Area',
+                        'value' => ['Area'],
+                    ],
+                    [
+                        'type' => 'Radio Buttons',
+                        'title' => 'custom option Radio Buttons',
+                        'value' => ['20 percent'],
+                    ],
+                    [
+                        'type' => 'Drop-down',
+                        'title' => 'custom option drop down',
+                        'value' => ['20 percent'],
+                    ],
+                    [
+                        'type' => 'Checkbox',
+                        'title' => 'custom option Checkbox',
+                        'value' => ['20 percent'],
+                    ],
+                    [
+                        'type' => 'Multiple Select',
+                        'title' => 'custom option Multiple Select',
+                        'value' => ['20 percent'],
+                    ],
+                    [
+                        'type' => 'Date',
+                        'title' => 'custom option Date',
+                        'value' => ['12/12/2014'],
+                    ],
+                    [
+                        'type' => 'Date & Time',
+                        'title' => 'custom option Date & Time',
+                        'value' => ['12/12/2014/12/30/AM'],
+                    ],
+                    [
+                        'type' => 'Time',
+                        'title' => 'custom option Time',
+                        'value' => ['12/12/2014/12/30/AM'],
+                    ],
+                ]
+            ],
+            'all_types_bundle_options' => [
+                'bundle_options' => [
+                    [
+                        'title' => 'Drop-down Option',
+                        'type' => 'Drop-down',
+                        'value' => [
+                            'name' => '100_dollar_product'
+                        ]
+                    ],
+                    [
+                        'title' => 'Radio Button Option',
+                        'type' => 'Radio Buttons',
+                        'value' => [
+                            'name' => '100_dollar_product'
+                        ]
+                    ],
+                    [
+                        'title' => 'Checkbox Option',
+                        'type' => 'Checkbox',
+                        'value' => [
+                            'name' => '100_dollar_product'
+                        ]
+                    ],
+                    [
+                        'title' => 'Multiple Select Option',
+                        'type' => 'Multiple',
+                        'value' => [
+                            'name' => '100_dollar_product'
+                        ]
+                    ],
+                ],
+            ],
+        ];
+        if (!isset($presets[$this->currentPreset])) {
+            return null;
+        }
+        return $presets[$this->currentPreset];
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle/Price.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle/Price.php
index 3a119dbf82f02d6a1e6219ebd24083a83ca2e540..b054a40a8a2b0ba514a7d0b5f8512cee629b1501 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle/Price.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle/Price.php
@@ -28,34 +28,44 @@ use Mtf\Fixture\FixtureInterface;
 
 /**
  * Class Price
- *
  * Data keys:
  *  - preset (Price verification preset name)
  *  - value (Price value)
- *
  */
 class Price implements FixtureInterface
 {
     /**
-     * @var \Mtf\Fixture\FixtureFactory
+     * Prepared dataSet data
+     *
+     * @var array
      */
-    protected $fixtureFactory;
+    protected $data;
 
     /**
+     * Data set configuration settings
+     *
+     * @var array
+     */
+    protected $params;
+
+    /**
+     * Current preset
+     *
      * @var string
      */
     protected $currentPreset;
 
     /**
+     * Constructor
+     *
+     * @constructor
      * @param array $params
-     * @param array $data
+     * @param array $data [optional]
      */
     public function __construct(array $params, array $data = [])
     {
         $this->params = $params;
-        if (isset($data['value'])) {
-            $this->data = $data['value'];
-        }
+        $this->data = (isset($data['value']) && $data['value'] != '-') ? $data['value'] : null;
         if (isset($data['preset'])) {
             $this->currentPreset = $data['preset'];
         }
@@ -95,37 +105,104 @@ class Price implements FixtureInterface
     }
 
     /**
+     * Get preset array
+     *
      * @return array|null
      */
     public function getPreset()
     {
         $presets = [
             'MAGETWO-23066' => [
-                'price_from' => '$115.00',
-                'price_to' => '$120.00',
+                'price_from' => '115.00',
+                'price_to' => '120.00',
                 'cart_price' => '145.00'
             ],
             'MAGETWO-23069' => [
-                'price_from' => '$115.00',
-                'price_to' => '$120.00',
+                'price_from' => '115.00',
+                'price_to' => '120.00',
                 'cart_price' => '126.00'
             ],
             'MAGETWO-23070' => [
-                'price_from' => '$40.00',
-                'price_to' => '$100.00',
+                'price_from' => '40.00',
+                'price_to' => '100.00',
                 'cart_price' => '100.00'
             ],
             'MAGETWO-23061' => [
-                'price_from' => '$32.00',
-                'price_to' => '$80.00',
+                'price_from' => '32.00',
+                'price_to' => '80.00',
+                'cart_price' => '80.00'
+            ],
+            'dynamic-200' => [
+                'price_from' => '200.00',
+                'price_to' => '500.00',
+                'cart_price' => '400.00'
+            ],
+            'fixed-24' => [
+                'price_from' => '96.00',
+                'price_to' => '97.00',
+                'cart_price' => '252.00'
+            ],
+            'fixed-1' => [
+                'price_from' => '1.00',
+                'price_to' => '10.00',
+                'cart_price' => '80.00'
+            ],
+            'dynamic-8' => [
+                'price_from' => '8.00',
+                'price_to' => '20.00',
+                'cart_price' => '80.00'
+            ],
+            'dynamic-32' => [
+                'price_from' => '32.00',
+                'price_to' => '80.00',
+                'cart_price' => '80.00'
+            ],
+            'dynamic-40' => [
+                'price_from' => '40.00',
+                'price_to' => '100.00',
+                'cart_price' => '100.00'
+            ],
+            'dynamic-50' => [
+                'price_from' => 'As low as $50.00',
+            ],
+            'fixed-115' => [
+                'price_from' => '115.00',
+                'price_to' => '120.00',
+                'cart_price' => '145.00'
+            ],
+            'fixed-126' => [
+                'price_from' => '115.00',
+                'price_to' => '120.00',
+                'cart_price' => '126.00'
+            ],
+            'fixed-15' => [
+                'price_from' => '15.00',
+                'price_to' => '16.00',
                 'cart_price' => '80.00'
-            ]
+            ],
+            'default_fixed' => [
+                'compare_price' => '755.00'
+            ],
+            'default_dynamic' => [
+                'compare_price' => [
+                    'price_from' => '100.00',
+                    'price_to' => '560.00'
+                ],
+            ],
+            'dynamic-100' => [
+                'price_from' => '100.00',
+                'price_to' => '560.00',
+                'cart_price' => '100.00'
+            ],
+            'fixed-756' => [
+                'price_from' => '755.00',
+                'price_to' => '756.00',
+                'cart_price' => '756.00'
+            ],
         ];
-
         if (!isset($presets[$this->currentPreset])) {
             return null;
         }
-
         return $presets[$this->currentPreset];
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/Curl/CreateBundle.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/Curl/CreateBundle.php
index 118f5679e772f29f4bcd78d204a0ceea9a609f18..6004f9dbc3461a83f57e37610071e5e13f27d5ef 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/Curl/CreateBundle.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/Curl/CreateBundle.php
@@ -89,7 +89,7 @@ class CreateBundle extends Curl
      */
     protected function _prepareData(array $params, $prefix = null)
     {
-        $data = array();
+        $data = [];
         foreach ($params as $key => $values) {
             if ($key == 'bundle_selections') {
                 $data = array_merge($data, $this->_getBundleData($values['value']));
@@ -171,7 +171,7 @@ class CreateBundle extends Curl
      */
     protected function _getUrl(array $config)
     {
-        $requestParams = isset($config['create_url_params']) ? $config['create_url_params'] : array();
+        $requestParams = isset($config['create_url_params']) ? $config['create_url_params'] : [];
         $params = '';
         foreach ($requestParams as $key => $value) {
             $params .= $key . '/' . $value . '/';
@@ -187,9 +187,9 @@ class CreateBundle extends Curl
      */
     protected function _getSelections(array $products)
     {
-        $data = array();
+        $data = [];
         foreach ($products as $product) {
-            $product = isset($product['data']) ? $product['data'] : array();
+            $product = isset($product['data']) ? $product['data'] : [];
             $data[] = $this->_prepareData($product) + ['delete' => ''];
         }
         return $data;
@@ -214,7 +214,7 @@ class CreateBundle extends Curl
         $url = $this->_getUrl($config);
         $curl = new BackendDecorator(new CurlTransport(), new Config);
         $curl->addOption(CURLOPT_HEADER, 1);
-        $curl->write(CurlInterface::POST, $url, '1.0', array(), $data);
+        $curl->write(CurlInterface::POST, $url, '1.0', [], $data);
         $response = $curl->read();
         $curl->close();
 
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Page/Product/CatalogProductView.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Page/Product/CatalogProductView.php
new file mode 100644
index 0000000000000000000000000000000000000000..455f7dbe322c662f4b8eb42bf89ceab2751e069a
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Page/Product/CatalogProductView.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Test\Page\Product;
+
+use Magento\Catalog\Test\Page\Product\CatalogProductView as ParentCatalogProductView;
+
+/**
+ * Class CatalogProductView
+ * Frontend bundle product view page
+ */
+class CatalogProductView extends ParentCatalogProductView
+{
+    const MCA = 'bundle/catalog/product/view';
+
+    /**
+     * Custom constructor
+     *
+     * @return void
+     */
+    protected function _init()
+    {
+        $this->_blocks['bundleViewBlock'] = [
+            'name' => 'bundleViewBlock',
+            'class' => 'Magento\Bundle\Test\Block\Catalog\Product\View',
+            'locator' => '.bundle-options-container',
+            'strategy' => 'css selector',
+        ];
+        parent::_init();
+    }
+
+    /**
+     * Bundle block on frontend
+     *
+     * @return \Magento\Bundle\Test\Block\Catalog\Product\View
+     */
+    public function getBundleViewBlock()
+    {
+        return $this->getBlockInstance('bundleViewBlock');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Page/Product/CatalogProductView.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Page/Product/CatalogProductView.xml
new file mode 100644
index 0000000000000000000000000000000000000000..789d4eabfc2d28fde1126bc7a2963ab94a5952a1
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Page/Product/CatalogProductView.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<page mca="catalog/product/view">
+    <block>
+        <name>bundleViewBlock</name>
+        <class>Magento\Bundle\Test\Block\Catalog\Product\View</class>
+        <locator>.bundle-options-container</locator>
+        <strategy>css selector</strategy>
+    </block>
+</page>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/Bundle.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/Bundle.php
index 6bb0cd180c3c9978f976635b55f7623ac493d597..5adb3bfafd0064ae9ff44c76ebcc7666e8f805bb 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/Bundle.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/Bundle.php
@@ -43,22 +43,22 @@ class Bundle extends Product
         if (isset($this->_data[$productType]['data']['fields']['price'])) {
             $required = array_merge_recursive(
                 $required,
-                array(
-                    'data' => array(
-                        'fields' => array(
-                            'price' => array(
+                [
+                    'data' => [
+                        'fields' => [
+                            'price' => [
                                 'value' => 60,
                                 'group' => Fixture\Product::GROUP_PRODUCT_DETAILS
-                            )
-                        ),
-                        'checkout' => array(
-                            'prices' => array(
+                            ]
+                        ],
+                        'checkout' => [
+                            'prices' => [
                                 'price_from' => 70,
                                 'price_to' => 72
-                            )
-                        )
-                    )
-                )
+                            ]
+                        ]
+                    ]
+                ]
             );
         } else {
             $required['data']['checkout']['prices'] = $this->_data[$productType]['data']['checkout']['prices'];
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/CatalogProductBundle.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/CatalogProductBundle.php
index 36d9d4e624eba64a487c896fcd6c4e6ab04efad7..709c1f2bcfb4d97b78a1269fadb036aecedf6818 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/CatalogProductBundle.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/CatalogProductBundle.php
@@ -82,6 +82,7 @@ class CatalogProductBundle extends AbstractRepository
             'sku' => 'sku_bundle_dynamic_product_%isolation%',
             'sku_type' => 'Dynamic',
             'price_type' => 'Dynamic',
+            'price' => ['value' => '-', 'preset' => 'default_dynamic'],
             'quantity_and_stock_status' => [
                 'qty' => 666.0000,
                 'is_in_stock' => 'In Stock',
@@ -107,7 +108,7 @@ class CatalogProductBundle extends AbstractRepository
             'sku' => 'sku_bundle_fixed_product_%isolation%',
             'sku_type' => 'Fixed',
             'price_type' => 'Fixed',
-            'price' => ['value' => 750.00, 'preset' => '-'],
+            'price' => ['value' => 750.00, 'preset' => 'default_fixed'],
             'tax_class_id' => ['dataSet' => 'Taxable Goods'],
             'quantity_and_stock_status' => [
                 'qty' => 666.0000,
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleDynamicTest.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleDynamicTest.php
old mode 100644
new mode 100755
index 54c801aa0cbe9b0aac5dc68cb05f751c221bfd20..3e5aed8a36ba3915030ba85e20c6cb88de182d91
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleDynamicTest.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleDynamicTest.php
@@ -61,8 +61,9 @@ class BundleDynamicTest extends Functional
         $productForm = $createProductPage->getForm();
         //Steps
         $manageProductsGrid->open();
-        $manageProductsGrid->getProductBlock()->addProduct('bundle');
-        $productForm->fillProduct($bundle);
+        $manageProductsGrid->getGridPageActionBlock()->addProduct('bundle');
+        $category = $bundle->getCategories()['category'];
+        $productForm->fill($bundle, null, $category);
         $createProductPage->getFormAction()->save();
         //Verification
         $createProductPage->getMessagesBlock()->assertSuccessMessage();
@@ -107,7 +108,10 @@ class BundleDynamicTest extends Functional
         $frontendHomePage->getTopmenu()->selectCategoryByName($product->getCategoryName());
         //Verification on category product list
         $productListBlock = $categoryPage->getListProductBlock();
-        $this->assertTrue($productListBlock->isProductVisible($product->getName()));
+        $this->assertTrue(
+            $productListBlock->isProductVisible($product->getName()),
+            'Product "' .  $product->getName() . '" is absent on category page'
+        );
         $productListBlock->openProductViewPage($product->getName());
         //Verification on product detail page
         $productViewBlock = $productPage->getViewBlock();
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleFixedTest.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleFixedTest.php
old mode 100644
new mode 100755
index bdb76ea8d8add043d539e7b426e1ed657cec5383..0fb7cab4454a0510be4aabcf5e99cb8246520a2d
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleFixedTest.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/BundleFixedTest.php
@@ -60,9 +60,10 @@ class BundleFixedTest extends Functional
         $createProductPage = Factory::getPageFactory()->getCatalogProductNew();
         //Steps
         $manageProductsGrid->open();
-        $manageProductsGrid->getProductBlock()->addProduct('bundle');
+        $manageProductsGrid->getGridPageActionBlock()->addProduct('bundle');
         $productForm = $createProductPage->getForm();
-        $productForm->fillProduct($bundle);
+        $category = $bundle->getCategories()['category'];
+        $productForm->fill($bundle, null, $category);
         $createProductPage->getFormAction()->save();
         //Verification
         $createProductPage->getMessagesBlock()->assertSuccessMessage();
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/CreateBundleProductEntityTest.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/CreateBundleProductEntityTest.php
new file mode 100755
index 0000000000000000000000000000000000000000..3c8ca29df084bf21546c9c7e4f1bf18dc9cfafca
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/CreateBundleProductEntityTest.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Test\TestCase;
+
+use Mtf\TestCase\Injectable;
+use Magento\Catalog\Test\Fixture\CatalogCategory;
+use Magento\Bundle\Test\Fixture\CatalogProductBundle;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew;
+
+/**
+ * Test Creation for CreateBundleProductEntity 
+ *
+ * Test Flow:
+ * 1. Login as admin
+ * 2. Navigate to the Products>Inventory>Catalog
+ * 3. Click on "+" dropdown and select Bundle Product type
+ * 4. Fill in all data according to data set
+ * 5. Save product
+ * 6. Verify created product
+ *
+ * @group Bundle_Product_(CS)
+ * @ZephyrId MAGETWO-24118
+ */
+class CreateBundleProductEntityTest extends Injectable
+{
+    /**
+     * Page product on backend
+     *
+     * @var CatalogProductIndex
+     */
+    protected $catalogProductIndex;
+
+    /**
+     * New page on backend
+     *
+     * @var CatalogProductNew
+     */
+    protected $catalogProductNew;
+
+    /**
+     * Persist category
+     *
+     * @param CatalogCategory $category
+     * @return array
+     */
+    public function __prepare(CatalogCategory $category)
+    {
+        $category->persist();
+
+        return [
+            'category' => $category
+        ];
+    }
+
+    /**
+     * Filling objects of the class
+     *
+     * @param CatalogProductIndex $catalogProductIndexNewPage
+     * @param CatalogProductNew $catalogProductNewPage
+     * @return void
+     */
+    public function __inject(
+        CatalogProductIndex $catalogProductIndexNewPage,
+        CatalogProductNew $catalogProductNewPage
+    ) {
+        $this->catalogProductIndex = $catalogProductIndexNewPage;
+        $this->catalogProductNew = $catalogProductNewPage;
+    }
+
+    /**
+     * Test create bundle product
+     *
+     * @param CatalogProductBundle $product
+     * @param CatalogCategory $category
+     * @return void
+     */
+    public function test(CatalogProductBundle $product, CatalogCategory $category)
+    {
+        $this->catalogProductIndex->open();
+        $this->catalogProductIndex->getGridPageActionBlock()->addProduct('bundle');
+        $productBlockForm = $this->catalogProductNew->getForm();
+        $productBlockForm->fill($product, null, $category);
+        $this->catalogProductNew->getFormAction()->save();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/CreateBundleProductEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/CreateBundleProductEntityTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..35d7c6279827ec87de81dffba59c17bf70b5ad26
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/CreateBundleProductEntityTest/test.csv
@@ -0,0 +1,15 @@
+"product/data/name";"product/data/sku_type";"product/data/sku";"product/data/status";"product/data/price_type";"product/data/price/value";"product/data/price/preset";"product/data/tax_class_id/dataSet";"product/data/quantity_and_stock_status/is_in_stock";"product/data/weight_type";"product/data/weight";"product/data/category";"product/data/description";"product/data/group_price/preset";"product/data/special_price";"product/data/special_from_date/pattern";"product/data/special_to_date/pattern";"product/data/tier_price/preset";"product/data/price_view";"product/data/stock_data/use_config_manage_stock";"product/data/stock_data/manage_stock";"product/data/shipment_type";"product/data/bundle_selections/preset";"product/data/bundle_selections/products";"product/data/checkout_data/preset";"product/data/custom_options/preset";"product/data/visibility";"product/data/use_config_gift_message_available";"product/data/gift_message_available";"constraint"
+"BundleProduct %isolation%";"-";"bundle_sku_%isolation%";"-";"-";"-";"-";"-";"-";"-";"-";"-";"Bundle Product Dynamic Required";"-";"-";"-";"-";"-";"-";"No";"No";"-";"default_dynamic";"catalogProductSimple::100_dollar_product,catalogProductVirtual::50_dollar_product";"default";"-";"-";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertBundleItemsOnProductPage"
+"BundleProduct %isolation%";"Fixed";"bundle_sku_%isolation%";"Product offline";"Dynamic";"-";"-";"-";"Out of Stock";"Dynamic";"-";"category_%isolation%";"-";"-";"-";"-";"-";"-";"-";"-";"-";"Separately";"default_dynamic";"catalogProductSimple::100_dollar_product,catalogProductVirtual::50_dollar_product";"default";"-";"Catalog, Search";"No";"Yes";"assertProductSaveMessage,  assertProductNotSearchableBySku"
+"BundleProduct %isolation%";"Dynamic";"bundle_sku_%isolation%";"Product online";"Dynamic";"-";"dynamic-200";"-";"In Stock";"Dynamic";"-";"category_%isolation%";"Bundle Product Dynamic";"-";"-";"-";"-";"-";"Price Range";"-";"-";"Together";"all_types_dynamic";"catalogProductSimple::100_dollar_product,catalogProductVirtual::50_dollar_product|catalogProductSimple::100_dollar_product,catalogProductVirtual::50_dollar_product|catalogProductSimple::100_dollar_product,catalogProductVirtual::50_dollar_product|catalogProductSimple::100_dollar_product,catalogProductVirtual::50_dollar_product";"all_types_bundle_options";"-";"Catalog, Search";"No";"Yes";"assertProductSaveMessage, assertProductInGrid, assertBundleProductForm, assertProductSearchableBySku, assertBundleProductPage, assertProductInStock, assertBundleItemsOnProductPage, assertProductVisibleInCategory, assertBundlePriceView, assertBundlePriceType"
+"BundleProduct %isolation%";"Fixed";"bundle_sku_%isolation%";"-";"Fixed";"10";"fixed-15";"None";"-";"Fixed";"10";"-";"Bundle Product Fixed Required";"-";"-";"-";"-";"-";"-";"-";"-";"-";"default_fixed";"catalogProductSimple::100_dollar_product,catalogProductVirtual::50_dollar_product";"default";"-";"-";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertBundleProductForm, assertProductSearchableBySku, assertBundleProductPage, assertBundleItemsOnProductPage"
+"BundleProduct %isolation%";"Fixed";"bundle_sku_%isolation%";"Product online";"Fixed";"100";"fixed-24";"Taxable Goods";"In Stock";"Fixed";"10";"category_%isolation%";"Bundle Product Fixed";"default";"-";"-";"-";"-";"As Low as";"-";"-";"Separately";"all_types_fixed";"catalogProductSimple::100_dollar_product,catalogProductVirtual::50_dollar_product|catalogProductSimple::100_dollar_product,catalogProductVirtual::50_dollar_product|catalogProductSimple::100_dollar_product,catalogProductVirtual::50_dollar_product|catalogProductSimple::100_dollar_product,catalogProductVirtual::50_dollar_product";"all_types_bundle_fixed_and_custom_options";"all_types";"Catalog, Search";"No";"No";"assertProductSaveMessage, assertProductInGrid, assertBundleProductForm, assertProductVisibleInCategory, assertBundleProductPage, assertProductInStock, assertGroupedPriceOnBundleProductPage, assertBundleItemsOnProductPage, assertBundlePriceView, assertBundlePriceType"
+"BundleProduct %isolation%";"Fixed";"bundle_sku_%isolation%";"Product online";"Fixed";"10";"fixed-1";"Taxable Goods";"Out of Stock";"Fixed";"10";"category_%isolation%";"-";"-";"10";"m/d/Y";"m/d/Y +3 days";"-";"Price Range";"No";"Yes";"Together";"with_not_required_options";"catalogProductSimple::100_dollar_product,catalogProductVirtual::50_dollar_product|catalogProductSimple::100_dollar_product,catalogProductVirtual::50_dollar_product";"with_not_required_options";"-";"Catalog";"No";"No";"assertProductSaveMessage, assertProductInGrid, assertBundleProductForm,  assertBundleProductPage, assertProductOutOfStock, assertBundlePriceView"
+"BundleProduct %isolation%";"Dynamic";"bundle_sku_%isolation%";"-";"Dynamic";"-";"dynamic-50";"-";"-";"Fixed";"10";"-";"-";"-";"-";"-";"-";"default";"As Low as";"No";"No";"Together";"default_dynamic";"catalogProductSimple::100_dollar_product,catalogProductVirtual::50_dollar_product";"default";"-";"Search";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertBundleProductForm, assertProductSearchableBySku, assertBundleProductPage, assertBundleItemsOnProductPage, assertTierPriceOnBundleProductPage"
+"Bundle Dynamic %isolation%";"Dynamic";"sku_bundle_dynamic_%isolation%";"-";"Dynamic";"-";"dynamic-8";"-";"-";"-";"-";"-";"-";"-";"20";"-";"-";"-";"-";"-";"-";"-";"default_dynamic";"catalogProductSimple::100_dollar_product,catalogProductSimple::40_dollar_product";"default";"-";"-";"-";"-";"assertProductSaveMessage, assertBundleInCategory"
+"Bundle Dynamic %isolation%";"Dynamic";"sku_bundle_dynamic_%isolation%";"-";"Dynamic";"-";"dynamic-32";"-";"-";"-";"-";"-";"-";"MAGETWO-23061";"-";"-";"-";"-";"-";"-";"-";"-";"default_dynamic";"catalogProductSimple::100_dollar_product,catalogProductSimple::40_dollar_product";"default";"-";"-";"-";"-";"assertProductSaveMessage, assertBundleInCategory, assertBundlePriceView, assertBundlePriceType"
+"Bundle Dynamic %isolation%";"Dynamic";"sku_bundle_dynamic_%isolation%";"-";"Dynamic";"-";"dynamic-40";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"default_dynamic";"catalogProductSimple::100_dollar_product,catalogProductSimple::40_dollar_product";"default";"-";"-";"-";"-";"assertProductSaveMessage, assertBundleInCategory, assertBundlePriceView, assertBundlePriceType"
+"Bundle Fixed %isolation%";"Fixed";"sku_bundle_fixed_%isolation%";"-";"Fixed";"110";"fixed-115";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"second";"catalogProductSimple::100_dollar_product,catalogProductSimple::40_dollar_product";"with_custom_options_1";"MAGETWO-23066";"-";"-";"-";"assertProductSaveMessage, assertBundleInCategory, assertBundlePriceView, assertBundlePriceType"
+"Bundle Fixed %isolation%";"Fixed";"sku_bundle_fixed_%isolation%";"-";"Fixed";"110";"fixed-126";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"second";"catalogProductSimple::100_dollar_product,catalogProductSimple::40_dollar_product";"with_custom_options_2";"MAGETWO-23069";"-";"-";"-";"assertProductSaveMessage, assertBundleInCategory, assertBundlePriceView, assertBundlePriceType"
+"Bundle Dynamic %isolation%";"Dynamic";"sku_bundle_dynamic_%isolation%";"-";"Dynamic";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"default_dynamic";"catalogProductSimple::100_dollar_product,catalogProductSimple::40_dollar_product";"default";"-";"-";"-";"-";"assertProductSaveMessage"
+"Bundle Fixed %isolation%";"Fixed";"sku_bundle_fixed_%isolation%";"-";"Fixed";"10";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"second";"catalogProductSimple::100_dollar_product,catalogProductSimple::40_dollar_product";"default";"-";"-";"-";"-";"assertProductSaveMessage"
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/EditBundleTest.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/EditBundleTest.php
old mode 100644
new mode 100755
index 5626dee51a54ed0f38d5f811ae439e590c36a78e..ed3b6068a95831ccd77e503f8b966e71f700775f
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/EditBundleTest.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/EditBundleTest.php
@@ -72,13 +72,11 @@ class EditBundleTest extends Functional
         $cachePage = Factory::getPageFactory()->getAdminCache();
 
         $productGridPage->open();
-        $gridBlock->searchAndOpen(
-            array(
-                'sku' => $product->getProductSku(),
-                'type' => 'Bundle Product'
-            )
-        );
-        $productForm->fillProduct($editProduct);
+        $gridBlock->searchAndOpen([
+            'sku' => $product->getProductSku(),
+            'type' => 'Bundle Product'
+        ]);
+        $productForm->fill($editProduct);
         $editProductPage->getFormAction()->save();
         //Verifying
         $editProductPage->getMessagesBlock()->assertSuccessMessage();
@@ -97,10 +95,10 @@ class EditBundleTest extends Functional
      */
     public function createDataProvider()
     {
-        return array(
-            array('getMagentoBundleBundleFixed'),
-            array('getMagentoBundleBundleDynamic')
-        );
+        return [
+            ['getMagentoBundleBundleFixed'],
+            ['getMagentoBundleBundleDynamic']
+        ];
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleProductEntityTest.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleProductEntityTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9cbf6996f500b7848bbd9a15f1f20418072600f9
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleProductEntityTest.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Test\TestCase;
+
+use Mtf\TestCase\Injectable;
+use Magento\Bundle\Test\Fixture\CatalogProductBundle;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+
+/**
+ * Test Creation for Update BundleProductEntity
+ *
+ * Test Flow:
+ *
+ * Precondition:
+ * 1. Category is created.
+ * 2. Bundle product is created.
+ *
+ * Steps
+ * 1. Login to backend.
+ * 2. Navigate to PRODUCTS > Catalog.
+ * 3. Select a product in the grid.
+ * 4. Edit test value(s) according to dataset.
+ * 5. Click "Save".
+ * 6. Perform asserts
+ *
+ *
+ * @group Bundle_Product_(MX)
+ * @ZephyrId MAGETWO-26195
+ */
+class UpdateBundleProductEntityTest extends Injectable
+{
+    /**
+     * Page product on backend
+     *
+     * @var CatalogProductIndex
+     */
+    protected $catalogProductIndex;
+
+    /**
+     * Edit page on backend
+     *
+     * @var CatalogProductEdit
+     */
+    protected $catalogProductEdit;
+
+    /**
+     * Injection data
+     *
+     * @param CatalogProductIndex $catalogProductIndexNewPage
+     * @param CatalogProductEdit $catalogProductEditPage
+     * @return void
+     */
+    public function __inject(
+        CatalogProductIndex $catalogProductIndexNewPage,
+        CatalogProductEdit $catalogProductEditPage
+    ) {
+        $this->catalogProductIndex = $catalogProductIndexNewPage;
+        $this->catalogProductEdit = $catalogProductEditPage;
+    }
+
+    /**
+     * Test update bundle product
+     *
+     * @param CatalogProductBundle $product
+     * @param CatalogProductBundle $originalProduct
+     * @return void
+     */
+    public function test(CatalogProductBundle $product, CatalogProductBundle $originalProduct)
+    {
+        $originalProduct->persist();
+        $this->catalogProductIndex->open();
+        $filter = ['sku' => $originalProduct->getSku()];
+        $this->catalogProductIndex->getProductGrid()->searchAndOpen($filter);
+        $this->catalogProductEdit->getForm()->fill($product);
+        $this->catalogProductEdit->getFormAction()->save();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleProductEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleProductEntityTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..440518b0e5a28b6bb3091b75096252385aaed8e5
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/UpdateBundleProductEntityTest/test.csv
@@ -0,0 +1,3 @@
+"originalProduct/dataSet";"product/data/name";"product/data/sku_type";"product/data/sku";"product/data/price/preset";"product/data/weight_type";"product/data/weight";"product/data/category_ids/presets";"product/data/description";"product/data/bundle_shipment_type";"product/data/bundle_selections/preset";"product/data/checkout_data/preset";"product/data/visibility";"constraint"
+"bundle_dynamic_product";"bundle_dynamic_%isolation%";"Fixed";"bundle_dynamic_%isolation%";"dynamic-100";"Fixed";"1";"-";"Bundle Product Fixed Required";"Together";"default_dynamic";"default";"-";"assertProductSaveMessage, assertProductInGrid, assertBundleItemsOnProductPage, assertBundleProductForm, assertBundleProductPage, assertProductInStock, assertBundlePriceView, assertBundlePriceType"
+"bundle_fixed_product";"bundle_dynamic_%isolation%";"Dynamic";"bundle_sku_%isolation%";"fixed-756";"Dynamic";"-";"default_subcategory";"-";"Separately";"default_fixed";"default";"Catalog, Search";"assertProductSaveMessage, assertProductInGrid, assertBundleItemsOnProductPage, assertBundleProductForm, assertBundleProductPage, assertProductInStock, assertProductVisibleInCategory, assertBundlePriceView, assertBundlePriceType"
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/global/constraint.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/global/constraint.xml
index 64b43a1d6aa70ce8ab7735d547f75b5eae91dc92..017c23441d638d0a28764d9745fa4bd2332bd4d9 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/global/constraint.xml
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/global/constraint.xml
@@ -33,19 +33,25 @@
             <category class="Magento\Catalog\Test\Fixture\Category" />
         </require>
     </assertBundleInCategory>
-    <assertBundleView module="Magento_Bundle">
+    <assertBundleItemsOnProductPage module="Magento_Bundle">
         <severeness>low</severeness>
-        <require>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
-            <product class="Magento\Bundle\Test\Fixture\CatalogProductBundle" />
-        </require>
-    </assertBundleView>
-    <assertBundleInCart module="Magento_Bundle">
+    </assertBundleItemsOnProductPage>
+    <assertBundlePriceView module="Magento_Bundle">
         <severeness>low</severeness>
-        <require>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
-            <product class="Magento\Bundle\Test\Fixture\CatalogProductBundle" />
-            <checkoutCart class="Magento\Checkout\Test\Page\CheckoutCart" />
-        </require>
-    </assertBundleInCart>
+    </assertBundlePriceView>
+    <assertBundlePriceType module="Magento_Bundle">
+        <severeness>low</severeness>
+    </assertBundlePriceType>
+    <assertBundleProductForm module="Magento_Bundle">
+        <severeness>low</severeness>
+    </assertBundleProductForm>
+    <assertTierPriceOnBundleProductPage module="Magento_Bundle">
+        <severeness>low</severeness>
+    </assertTierPriceOnBundleProductPage>
+    <assertBundleProductPage module="Magento_Bundle">
+        <severeness>low</severeness>
+    </assertBundleProductPage>
+    <assertGroupedPriceOnBundleProductPage module="Magento_Bundle">
+        <severeness>low</severeness>
+    </assertGroupedPriceOnBundleProductPage>
 </constraint>
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/global/fixture.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/global/fixture.xml
index dbeb096b70bab750886b4ac77ba72449eff9d1be..36e822cde00dba9e147f719d1370a964f0c14658 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/global/fixture.xml
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/global/fixture.xml
@@ -40,7 +40,7 @@
                 <backend_type>virtual</backend_type>
                 <is_required>1</is_required>
                 <group>bundle</group>
-                <fixture>Magento\Bundle\Test\Fixture\Bundle\Selections</fixture>
+                <fixture>Magento\Bundle\Test\Fixture\Bundle\BundleSelections</fixture>
             </bundle_selections>
         </fields>
         <data_set>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/CategoryForm.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/CategoryForm.xml
index 5db9812bcfe59206ff262f156d8c79d5a9e5c945..16a88a95a6893df51a5a398d4ed1a21c80b9752d 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/CategoryForm.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/CategoryForm.xml
@@ -66,6 +66,15 @@
             <default_sort_by>
                 <input>select</input>
             </default_sort_by>
+            <display_mode>
+                <input>select</input>
+            </display_mode>
+            <landing_page>
+                <input>select</input>
+            </landing_page>
+            <is_anchor>
+                <input>select</input>
+            </is_anchor>
         </fields>
     </display_setting>
     <custom_design>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Widget/Chooser.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Widget/Chooser.php
new file mode 100644
index 0000000000000000000000000000000000000000..ce943c65d2dfef5d0ed64ba2e72d0f73bfa996c6
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Widget/Chooser.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Category\Widget;
+
+use Mtf\Block\Block;
+use Mtf\Client\Element\Locator;
+
+/**
+ * Class CategoryChooser
+ * Backend Cms Page select category block
+ */
+class Chooser extends Block
+{
+    /**
+     * Category name selector
+     *
+     * @var string
+     */
+    protected $categoryNameSelector = "//a/span[contains(text(),'%s')]";
+
+    /**
+     * Select category by name
+     *
+     * @param string $name
+     * @return void
+     */
+    public function selectCategoryByName($name)
+    {
+        $this->_rootElement->find(sprintf($this->categoryNameSelector, $name), Locator::SELECTOR_XPATH)->click();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/FormPageActions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/FormPageActions.php
index a6a178968c474b17d6362e69f9b07f8cc5b1e8d5..3aaeb9b765da6ad8ef043a9ed6dec7bce67d1b90 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/FormPageActions.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/FormPageActions.php
@@ -27,8 +27,8 @@ namespace Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\Set;
 use Magento\Backend\Test\Block\FormPageActions as AbstractFormPageActions;
 
 /**
- * Class Form
- * Catalog Product Attribute form
+ * Class FormPageActions
+ * Form page actions in Attribute Set page
  */
 class FormPageActions extends AbstractFormPageActions
 {
@@ -38,4 +38,11 @@ class FormPageActions extends AbstractFormPageActions
      * @var string
      */
     protected $saveButton = '.save-attribute-set';
+
+    /**
+     * "Delete" button
+     *
+     * @var string
+     */
+    protected $deleteButton = '.delete';
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/Main.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/Main.php
index 627f5469f01d4ef986250ccd58bdfc45426b5211..fec00fd3d314902169768d4f0b3d22b1d9f49fda 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/Main.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/Main.php
@@ -47,6 +47,20 @@ class Main extends Block
      */
     protected $attribute = './/*[contains(@class,"x-tree-root-node")]//div/a/span[text()="%s"]';
 
+    /**
+     * Attribute label locator
+     *
+     * @var string
+     */
+    protected $attributeLabel = ".//*[contains(@id,'tree-div2')]//li[@class='x-tree-node']/div/a/span[text()='%s']";
+
+    /**
+     * Add group button locator
+     *
+     * @var string
+     */
+    protected $addGroupButton = '[data-ui-id="adminhtml-catalog-product-set-edit-add-group-button"]';
+
     /**
      * Move Attribute to Attribute Group
      *
@@ -54,7 +68,7 @@ class Main extends Block
      * @param string $attributeGroup
      * @return void
      */
-    public function moveAttribute($attributeData, $attributeGroup)
+    public function moveAttribute(array $attributeData, $attributeGroup)
     {
         if (isset($attributeData['attribute_code'])) {
             $attribute = $attributeData['attribute_code'];
@@ -82,16 +96,42 @@ class Main extends Block
     /**
      * Checks present Product Attribute on product_set Groups
      *
-     * @param $attributeLabel
+     * @param string $attributeLabel
      * @return bool
      */
     public function checkProductAttribute($attributeLabel)
     {
         $attributeLabelLocator = sprintf(
-            ".//*[contains(@class,'x-tree-root-node')]//li[@class='x-tree-node']/div/a/span[text()='%s']",
+            ".//*[contains(@id,'tree-div1')]//li[@class='x-tree-node']/div/a/span[text()='%s']",
             $attributeLabel
         );
 
         return $this->_rootElement->find($attributeLabelLocator, Locator::SELECTOR_XPATH)->isVisible();
     }
+
+    /**
+     * Checks present Unassigned Product Attribute
+     *
+     * @param string $attributeLabel
+     * @return bool
+     */
+    public function checkUnassignedProductAttribute($attributeLabel)
+    {
+        $attributeLabelLocator = sprintf($this->attributeLabel, $attributeLabel);
+
+        return $this->_rootElement->find($attributeLabelLocator, Locator::SELECTOR_XPATH)->isVisible();
+    }
+
+    /**
+     * Add attribute set group to Attribute Set
+     *
+     * @param string $groupName
+     * @return void
+     */
+    public function addAttributeSetGroup($groupName)
+    {
+        $this->_rootElement->find($this->addGroupButton)->click();
+        $this->_rootElement->setAlertText($groupName);
+        $this->_rootElement->acceptAlert();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/Main/EditForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/Main/EditForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..18607bb1587507573fde7f47f9e6aa112060da9a
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/Main/EditForm.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\Set\Main;
+
+use Mtf\Block\Form as AbstractForm;
+
+/**
+ * Class EditForm
+ * Attribute Set form
+ */
+class EditForm extends AbstractForm
+{
+    //
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/Main/EditForm.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/Main/EditForm.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a17059154de6a53b8afcf021c1dc39775687536d
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/Main/EditForm.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <attribute_set_name />
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/AdvancedPricingTab.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/AdvancedPricingTab.php
old mode 100644
new mode 100755
index 192f4ea671de1f20458782de0b20ea119248890a..bdcbd5fa3022b5ef431254b884c7afc9a22ac8df
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/AdvancedPricingTab.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/AdvancedPricingTab.php
@@ -109,7 +109,7 @@ class AdvancedPricingTab extends Tab
                 }
             } elseif (!empty($field['value'])) {
                 $data = $this->dataMapping([$fieldName => $field]);
-                $formData[$fieldName] = $this->_getData($data, $this->_rootElement);
+                $formData += $this->_getData($data, $this->_rootElement);
             }
         }
 
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/AdvancedPricingTab/OptionGroup.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/AdvancedPricingTab/OptionGroup.php
index 9d98751f3928403d9ae0775a211ab46f93d74dd4..72a5d99b7f89600bb4ccb7ebd5afdbdea7e856ff 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/AdvancedPricingTab/OptionGroup.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/AdvancedPricingTab/OptionGroup.php
@@ -25,13 +25,13 @@
 namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\AdvancedPricingTab;
 
 use Mtf\Client\Element;
-use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Options;
+use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\AbstractOptions;
 
 /**
  * Class OptionField
  * Form "Group prices" on the tab "Extended price"
  */
-class OptionGroup extends Options
+class OptionGroup extends AbstractOptions
 {
     /**
      * 'Add Group Price' button selector
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/AdvancedPricingTab/OptionTier.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/AdvancedPricingTab/OptionTier.php
index f62941712b8a126acc23c4a906e1beb15d1efa05..bafabe132a5ad6cfc8f2115763b6a17933a2f797 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/AdvancedPricingTab/OptionTier.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/AdvancedPricingTab/OptionTier.php
@@ -25,13 +25,13 @@
 namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\AdvancedPricingTab;
 
 use Mtf\Client\Element;
-use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Options;
+use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\AbstractOptions;
 
 /**
  * Class OptionTier
  * Form 'Tier prices' on the 'Advanced Pricing' tab
  */
-class OptionTier extends Options
+class OptionTier extends AbstractOptions
 {
     /**
      * 'Add Tier' button selector
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/CustomOptionsTab.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options.php
similarity index 83%
rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/CustomOptionsTab.php
rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options.php
index 3238cb19301b619179fb609120a578b1e1a666e3..3b3056997e8ed85d8f7f472d312b6377ac864db5 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/CustomOptionsTab.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options.php
@@ -22,17 +22,17 @@
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
 
-namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit;
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab;
 
 use Mtf\ObjectManager;
 use Mtf\Client\Element;
 use Magento\Backend\Test\Block\Widget\Tab;
 
 /**
- * Class CustomOptionsTab
+ * Class Options
  * Product custom options tab
  */
-class CustomOptionsTab extends Tab
+class Options extends Tab
 {
     /**
      * Custom option row CSS locator
@@ -41,16 +41,6 @@ class CustomOptionsTab extends Tab
      */
     protected $customOptionRow = '#product-custom-options-content .fieldset-wrapper:nth-child(%d)';
 
-    /**
-     * Class name 'Subform' of the main tab form
-     *
-     * @var array
-     */
-    protected $childrenForm = [
-        'Field' => 'CustomOptionsTab\OptionField',
-        'Drop-down' => 'CustomOptionsTab\OptionDropDown'
-    ];
-
     /**
      * Add an option button
      *
@@ -85,12 +75,10 @@ class CustomOptionsTab extends Tab
             $this->_fill($data, $rootElement);
 
             // Fill subform
-            if (isset($field['type']) && isset($this->childrenForm[$field['type']])
-                && !empty($options)
-            ) {
-                /** @var \Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Options $optionsForm */
+            if (isset($field['type']) && !empty($options)) {
+                /** @var \Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\OptionsAbstract $optionsForm */
                 $optionsForm = $this->blockFactory->create(
-                    __NAMESPACE__ . '\\' . $this->childrenForm[$field['type']],
+                    __NAMESPACE__ . '\Options\Type\\' . $this->optionNameConvert($field['type']),
                     ['element' => $rootElement]
                 );
 
@@ -137,12 +125,10 @@ class CustomOptionsTab extends Tab
             $formDataItem = $this->_getData($data, $rootElement);
 
             // Data collection subform
-            if (isset($field['type']) && isset($this->childrenForm[$field['type']])
-                && !empty($options)
-            ) {
-                /** @var \Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Options $optionsForm */
+            if (isset($field['type']) && !empty($options)) {
+                /** @var \Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\OptionsAbstract $optionsForm */
                 $optionsForm = $this->blockFactory->create(
-                    __NAMESPACE__ . '\\' . $this->childrenForm[$field['type']],
+                    __NAMESPACE__ . '\Options\Type\\' . $this->optionNameConvert($field['type']),
                     ['element' => $rootElement]
                 );
 
@@ -158,4 +144,19 @@ class CustomOptionsTab extends Tab
 
         return $formData;
     }
+
+    /**
+     * Convert option name
+     *
+     * @param string $str
+     * @return string
+     */
+    protected function optionNameConvert($str)
+    {
+        $str = str_replace([' ', '&'], "", $str);
+        if ($end = strpos($str, '-')) {
+            $str = substr($str, 0, $end) . ucfirst(substr($str, ($end + 1)));
+        }
+        return $str;
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Options.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/AbstractOptions.php
similarity index 92%
rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Options.php
rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/AbstractOptions.php
index f24a3a59eaa026c8f4d9f6c7c995f73bedefa9c6..7eb94ac733e38a1b50f6069e3bf69e0714edd893 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Options.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/AbstractOptions.php
@@ -22,16 +22,16 @@
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
 
-namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit;
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options;
 
 use Mtf\Client\Element;
 use Magento\Backend\Test\Block\Widget\Tab;
 
 /**
- * Abstract class Options
+ * Abstract class AbstractOptions
  * Parent class for all forms of product options
  */
-abstract class Options extends Tab
+abstract class AbstractOptions extends Tab
 {
     /**
      * Fills in the form of an array of input data
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Area.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Area.php
new file mode 100644
index 0000000000000000000000000000000000000000..da9564cae1bcd312ad0b5ea2020fb026636146cb
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Area.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\Type;
+
+use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\AbstractOptions;
+
+/**
+ * Class Area
+ * Form "Text area" on tab product "Custom options"
+ */
+class Area extends AbstractOptions
+{
+    // Parent behavior
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/CustomOptionsTab/OptionField.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Area.xml
similarity index 100%
rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/CustomOptionsTab/OptionField.xml
rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Area.xml
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Checkbox.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Checkbox.php
new file mode 100644
index 0000000000000000000000000000000000000000..e1ff5cdc94970e397221a623086e364b23839b38
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Checkbox.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\Type;
+
+use Mtf\Client\Element;
+use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\Type\DropDown as AbstractOptions;
+
+/**
+ * Class Checkbox
+ * Form "Option checkbox" on tab product "Custom options"
+ */
+class Checkbox extends AbstractOptions
+{
+    // Parent behavior
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/CustomOptionsTab/OptionDropDown.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Checkbox.xml
similarity index 100%
rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/CustomOptionsTab/OptionDropDown.xml
rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Checkbox.xml
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Date.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Date.php
new file mode 100644
index 0000000000000000000000000000000000000000..0d01fc2e08e6eb034128ddd522a5fd9df493ce0c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Date.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\Type;
+
+use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\AbstractOptions;
+
+/**
+ * Class Date
+ * Form "Date" on tab product "Custom options"
+ */
+class Date extends AbstractOptions
+{
+    // Parent behavior
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Date.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Date.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d127f10cc56d9bfcf2cea32f9a0891c8cc539398
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Date.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <price>
+            <selector>[id$='_price']</selector>
+        </price>
+        <price_type>
+            <selector>[id$='_price_type']</selector>
+            <input>select</input>
+        </price_type>
+        <sku>
+            <selector>[name$='[sku]']</selector>
+        </sku>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/DateTime.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/DateTime.php
new file mode 100644
index 0000000000000000000000000000000000000000..39ae959d3f89afa6a694d88b2fbd020953696323
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/DateTime.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\Type;
+
+use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\AbstractOptions;
+
+/**
+ * Class DateTime
+ * Form "Date & Time" on tab product "Custom options"
+ */
+class DateTime extends AbstractOptions
+{
+    // Parent behavior
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/DateTime.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/DateTime.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d127f10cc56d9bfcf2cea32f9a0891c8cc539398
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/DateTime.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <price>
+            <selector>[id$='_price']</selector>
+        </price>
+        <price_type>
+            <selector>[id$='_price_type']</selector>
+            <input>select</input>
+        </price_type>
+        <sku>
+            <selector>[name$='[sku]']</selector>
+        </sku>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/CustomOptionsTab/OptionDropDown.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/DropDown.php
similarity index 83%
rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/CustomOptionsTab/OptionDropDown.php
rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/DropDown.php
index 54a92ab01bd5cbd1e93207b6c244b22fd68dfbd2..c9a21a000810046a256e6f54a8b9be3ba1f56088 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/CustomOptionsTab/OptionDropDown.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/DropDown.php
@@ -22,23 +22,23 @@
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
 
-namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\CustomOptionsTab;
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\Type;
 
 use Mtf\Client\Element;
-use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Options;
+use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\AbstractOptions;
 
 /**
- * Class OptionDropDown
+ * Class DropDown
  * Form "Option dropdown" on tab product "Custom options"
  */
-class OptionDropDown extends Options
+class DropDown extends AbstractOptions
 {
     /**
      * Add button css selector
      *
      * @var string
      */
-    private $buttonAddLocator = '[id$="_add_select_row"]';
+    protected $buttonAddLocator = '[id$="_add_select_row"]';
 
     /**
      * Fill the form
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/DropDown.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/DropDown.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4dac6efd003d6b8f317418a7e16f3a8eafdec485
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/DropDown.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <title>
+            <selector>[id$="_title"]</selector>
+        </title>
+        <price>
+            <selector>[id$="_price"]</selector>
+        </price>
+        <price_type>
+            <selector>[id$="_price_type"]</selector>
+            <input>select</input>
+        </price_type>
+        <sku>
+            <selector>[name$='[sku]']</selector>
+        </sku>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Field.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Field.php
new file mode 100644
index 0000000000000000000000000000000000000000..87d0807614f6b42f1855dcb32e3d1f98bfc253e6
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Field.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\Type;
+
+use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\AbstractOptions;
+
+/**
+ * Class Field
+ * Form "Text field" on tab product "Custom options"
+ */
+class Field extends AbstractOptions
+{
+    // Parent behavior
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Field.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Field.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e5b42e7e52488ab41a91cd305821910f72738cbd
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Field.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <price>
+            <selector>[id$='_price']</selector>
+        </price>
+        <price_type>
+            <selector>[id$='_price_type']</selector>
+            <input>select</input>
+        </price_type>
+        <sku>
+            <selector>[name$='[sku]']</selector>
+        </sku>
+        <max_characters>
+            <selector>[name$='[max_characters]']</selector>
+        </max_characters>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/File.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/File.php
new file mode 100644
index 0000000000000000000000000000000000000000..b2591e0af88ecd62e091e06b0f57ca9f32d36b9e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/File.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\Type;
+
+use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\AbstractOptions;
+
+/**
+ * Class File
+ * Form "Text file" on tab product "Custom options"
+ */
+class File extends AbstractOptions
+{
+    // Parent behavior
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/File.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/File.xml
new file mode 100644
index 0000000000000000000000000000000000000000..46f641b1ef3b2ae983ae76d89db60e6e8b01f1f4
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/File.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <price>
+            <selector>[name$='[price]']</selector>
+        </price>
+        <price_type>
+            <selector>[name$='[price_type]']</selector>
+            <input>select</input>
+        </price_type>
+        <sku>
+            <selector>[name$='[sku]']</selector>
+        </sku>
+        <file_extension>
+            <selector>[name$='[file_extension]']</selector>
+        </file_extension>
+        <image_size_x>
+            <selector>[name$='[image_size_x]']</selector>
+        </image_size_x>
+        <image_size_y>
+            <selector>[name$='[image_size_y]']</selector>
+        </image_size_y>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/MultipleSelect.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/MultipleSelect.php
new file mode 100644
index 0000000000000000000000000000000000000000..8523086ea1649d4a4569be1dfe96767618cf0e8e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/MultipleSelect.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\Type;
+
+use Mtf\Client\Element;
+use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\Type\DropDown as AbstractOptions;
+
+/**
+ * Class MultipleSelect
+ * Form "Option multiple select" on tab product "Custom options"
+ */
+class MultipleSelect extends AbstractOptions
+{
+    // Parent behavior
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/MultipleSelect.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/MultipleSelect.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4dac6efd003d6b8f317418a7e16f3a8eafdec485
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/MultipleSelect.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <title>
+            <selector>[id$="_title"]</selector>
+        </title>
+        <price>
+            <selector>[id$="_price"]</selector>
+        </price>
+        <price_type>
+            <selector>[id$="_price_type"]</selector>
+            <input>select</input>
+        </price_type>
+        <sku>
+            <selector>[name$='[sku]']</selector>
+        </sku>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/RadioButtons.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/RadioButtons.php
new file mode 100644
index 0000000000000000000000000000000000000000..ca0a944d07c1b9297e6c92ae0b66456a60ed4c50
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/RadioButtons.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\Type;
+
+use Mtf\Client\Element;
+use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\Type\DropDown as AbstractOptions;
+
+/**
+ * Class RadioButtons
+ * Form "Option radio button" on tab product "Custom options"
+ */
+class RadioButtons extends AbstractOptions
+{
+    // Parent behavior
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/RadioButtons.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/RadioButtons.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4dac6efd003d6b8f317418a7e16f3a8eafdec485
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/RadioButtons.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <title>
+            <selector>[id$="_title"]</selector>
+        </title>
+        <price>
+            <selector>[id$="_price"]</selector>
+        </price>
+        <price_type>
+            <selector>[id$="_price_type"]</selector>
+            <input>select</input>
+        </price_type>
+        <sku>
+            <selector>[name$='[sku]']</selector>
+        </sku>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Time.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Time.php
new file mode 100644
index 0000000000000000000000000000000000000000..5307fb3ff3498668cf07d437d08ba218512fea06
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Time.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\Type;
+
+use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options\AbstractOptions;
+
+/**
+ * Class Time
+ * Form "Date time" on tab product "Custom options"
+ */
+class Time extends AbstractOptions
+{
+    // Parent behavior
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Time.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Time.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d127f10cc56d9bfcf2cea32f9a0891c8cc539398
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Options/Type/Time.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <price>
+            <selector>[id$='_price']</selector>
+        </price>
+        <price_type>
+            <selector>[id$='_price_type']</selector>
+            <input>select</input>
+        </price_type>
+        <sku>
+            <selector>[name$='[sku]']</selector>
+        </sku>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/ProductDetails/CategoryIds.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/ProductDetails/CategoryIds.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ffcee808d0468eb8aa5550edc85fcd44c3bc558
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/ProductDetails/CategoryIds.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\ProductDetails;
+
+use Mtf\Client\Driver\Selenium\Element\MultisuggestElement;
+
+/**
+ * Class CategoryIds
+ * Typified element class for category element
+ */
+class CategoryIds extends MultisuggestElement
+{
+    /**
+     * Selector suggest input
+     *
+     * @var string
+     */
+    protected $suggest = '#category_ids-suggest';
+
+    /**
+     * Selector item of search result
+     *
+     * @var string
+     */
+    protected $resultItem = './/li/a/span[@class="category-label"][text()="%s"]';
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/ProductDetails/ProductOnlineSwitcher.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/ProductDetails/ProductOnlineSwitcher.php
new file mode 100644
index 0000000000000000000000000000000000000000..c61f192582b14b3b013e72e19e2d884386cec5a7
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/ProductDetails/ProductOnlineSwitcher.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\ProductDetails;
+
+use Mtf\Client\Driver\Selenium\Element;
+
+/**
+ * Class ProductOnlineSwitcher
+ * Typified element class for product status element
+ */
+class ProductOnlineSwitcher extends Element
+{
+    /**
+     * CSS locator button status of the product
+     *
+     * @var string
+     */
+    protected $onlineSwitcher = '#product-online-switcher%s + [for="product-online-switcher"]';
+
+    /**
+     * Set value
+     *
+     * @param string $value
+     * @return void
+     * @throws \Exception
+     */
+    public function setValue($value)
+    {
+        if (!$this->find(sprintf($this->onlineSwitcher, ''))->isVisible()) {
+            throw new \Exception("Can't find product online switcher.");
+        }
+        if (($value === 'Product offline' && $this->find(sprintf($this->onlineSwitcher, ':checked'))->isVisible())
+            || ($value === 'Product online'
+                && $this->find(sprintf($this->onlineSwitcher, ':not(:checked)'))->isVisible()
+            )
+        ) {
+            $this->find(sprintf($this->onlineSwitcher, ''))->click();
+        }
+    }
+
+    /**
+     * Get value
+     *
+     * @return string
+     * @throws \Exception
+     */
+    public function getValue()
+    {
+        if (!$this->find(sprintf($this->onlineSwitcher, ''))->isVisible()) {
+            throw new \Exception("Can't find product online switcher.");
+        }
+        if ($this->find(sprintf($this->onlineSwitcher, ':checked'))->isVisible()) {
+            return 'Product online';
+        }
+        return 'Product offline';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Search.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Search.php
new file mode 100644
index 0000000000000000000000000000000000000000..00a7d7297c521758210c1534713976fae99b5b03
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Search.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Variations;
+
+use Mtf\Client\Element;
+use Mtf\Client\Driver\Selenium\Element\SuggestElement;
+use Magento\Catalog\Test\Fixture\CatalogProductAttribute;
+
+/**
+ * Class FormAttributeSearch
+ * Form Attribute Search on Product page
+ */
+class Search extends SuggestElement
+{
+    /**
+     * Attribute Set locator
+     *
+     * @var string
+     */
+    protected $value = '.action-toggle > span';
+
+    /**
+     * Attribute Set button
+     *
+     * @var string
+     */
+    protected $actionToggle = '.action-toggle';
+
+    /**
+     * Search attribute result locator
+     *
+     * @var string
+     */
+    protected $searchResult = '.mage-suggest-dropdown .ui-corner-all';
+
+    /**
+     * Set value
+     *
+     * @param string $value
+     * @return void
+     */
+    public function setValue($value)
+    {
+        $this->find($this->actionToggle)->click();
+        parent::setValue($value);
+    }
+
+    /**
+     * Get value
+     *
+     * @return string
+     */
+    public function getValue()
+    {
+        return $this->find($this->value)->getText();
+    }
+
+    /**
+     * Checking not exist configurable attribute in search result
+     *
+     * @param CatalogProductAttribute $productAttribute
+     * @return bool
+     */
+    public function isExistAttributeInSearchResult(CatalogProductAttribute $productAttribute)
+    {
+        $attribute = $productAttribute->getFrontendLabel();
+        $searchResult = $this->find($this->searchResult);
+
+        $this->find($this->suggest)->setValue($attribute);
+        if (!$searchResult->isVisible()) {
+            return false;
+        }
+        if ($searchResult->getText() == $attribute) {
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Websites/StoreTree.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Websites/StoreTree.php
new file mode 100755
index 0000000000000000000000000000000000000000..1fbcd598a2ac08d2e30408a1f0c229cfcc9a256c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Websites/StoreTree.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Websites;
+
+use Mtf\Client\Element\Locator;
+use Mtf\Client\Driver\Selenium\Element;
+
+/**
+ * Class StoreTree
+ * Typified element class for store tree element
+ */
+class StoreTree extends Element
+{
+    /**
+     * Selector for website checkbox
+     *
+     * @var string
+     */
+    protected $website = './/*[@class="website-name"]/label[contains(text(),"%s")]/../input';
+
+    /**
+     * Selector for selected website checkbox
+     *
+     * @var string
+     */
+    protected $selectedWebsite = './/*[@class="website-name"]/input[@checked="checked"][%d]/../label';
+
+    /**
+     * Set value
+     *
+     * @param array|string $values
+     * @return void
+     * @throws \Exception
+     */
+    public function setValue($values)
+    {
+        $values = is_array($values) ? $values : [$values];
+        foreach ($values as $value) {
+            $website = $this->find(sprintf($this->website, $value), Locator::SELECTOR_XPATH);
+            if (!$website->isVisible()) {
+                throw new \Exception("Can't find website: \"{$value}\".");
+            }
+            if (!$website->isSelected()) {
+                $website->click();
+            }
+        }
+    }
+
+    /**
+     * Get value
+     *
+     * @return array
+     */
+    public function getValue()
+    {
+        $values = [];
+
+        $count = 1;
+        $website = $this->find(sprintf($this->selectedWebsite, $count), Locator::SELECTOR_XPATH);
+        while ($website->isVisible()) {
+            $values[] = $website->getText();
+            ++$count;
+            $website = $this->find(sprintf($this->selectedWebsite, $count), Locator::SELECTOR_XPATH);
+        }
+        return $values;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/FormPageActions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/FormPageActions.php
index 467ad465bc9552d906b53f9c4a98a8e5d0fe7126..b5fe622c14b4eba0372390a7201eeaeb5c5b65c0 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/FormPageActions.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/FormPageActions.php
@@ -25,6 +25,7 @@
 namespace Magento\Catalog\Test\Block\Adminhtml\Product;
 
 use Mtf\Page\BackendPage;
+use Mtf\Client\Element\Locator;
 use Mtf\Fixture\FixtureInterface;
 use Magento\Backend\Test\Block\FormPageActions as ParentFormPageActions;
 
@@ -34,6 +35,35 @@ use Magento\Backend\Test\Block\FormPageActions as ParentFormPageActions;
  */
 class FormPageActions extends ParentFormPageActions
 {
+    /**
+     * Save and create new product - 'Save & New'
+     */
+    const SAVE_NEW = 'new';
+
+    /**
+     * Save and create a duplicate product - 'Save & Duplicate'
+     */
+    const SAVE_DUPLICATE = 'duplicate';
+
+    /**
+     * Save and close the product page - 'Save & Close'
+     */
+    const SAVE_CLOSE = 'close';
+
+    /**
+     * CSS selector toggle "Save button"
+     *
+     * @var string
+     */
+    protected $toggleButton = '[data-ui-id="page-actions-toolbar-save-split-button-dropdown"]';
+
+    /**
+     * Save type item
+     *
+     * @var string
+     */
+    protected $saveTypeItem = '#save-split-button-%s-button';
+
     /**
      * "Save" button
      *
@@ -55,4 +85,37 @@ class FormPageActions extends ParentFormPageActions
         $affectedAttributeSetForm = $page->getAffectedAttributeSetForm();
         $affectedAttributeSetForm->fill($product)->confirm();
     }
+
+    /**
+     * Click save and duplicate action
+     *
+     * @return void
+     */
+    public function saveAndDuplicate()
+    {
+        $this->_rootElement->find($this->toggleButton, Locator::SELECTOR_CSS)->click();
+        $this->_rootElement->find(sprintf($this->saveTypeItem, static::SAVE_DUPLICATE), Locator::SELECTOR_CSS)->click();
+    }
+
+    /**
+     * Click save and new action
+     *
+     * @return void
+     */
+    public function saveAndNew()
+    {
+        $this->_rootElement->find($this->toggleButton, Locator::SELECTOR_CSS)->click();
+        $this->_rootElement->find(sprintf($this->saveTypeItem, static::SAVE_NEW), Locator::SELECTOR_CSS)->click();
+    }
+
+    /**
+     * Click save and new action
+     *
+     * @return void
+     */
+    public function saveAndClose()
+    {
+        $this->_rootElement->find($this->toggleButton, Locator::SELECTOR_CSS)->click();
+        $this->_rootElement->find(sprintf($this->saveTypeItem, static::SAVE_CLOSE), Locator::SELECTOR_CSS)->click();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Grid.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Grid.php
index 316afd6e097f425dc4b73a7717dfb80322ab0fc3..4b628be44b590307fb82c8214b8a6714181da763 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Grid.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Grid.php
@@ -34,6 +34,8 @@ class Grid extends ParentGrid
 {
     /**
      * Initialize block elements
+     *
+     * @var array
      */
     protected $filters = [
         'name' => [
@@ -51,6 +53,20 @@ class Grid extends ParentGrid
         ],
         'price_to' => [
             'selector' => '#productGrid_product_filter_price_to'
+        ],
+        'qty_from' => [
+            'selector' => '#productGrid_product_filter_qty_from'
+        ],
+        'qty_to' => [
+            'selector' => '#productGrid_product_filter_qty_to'
+        ],
+        'visibility' => [
+            'selector' => '#productGrid_product_filter_visibility',
+            'input' => 'select'
+        ],
+        'status' => [
+            'selector' => '#productGrid_product_filter_status',
+            'input' => 'select'
         ]
     ];
 
@@ -60,7 +76,7 @@ class Grid extends ParentGrid
      * @param array $items
      * @return void
      */
-    public function updateAttributes(array $items = array())
+    public function updateAttributes(array $items = [])
     {
         $this->massaction('Update Attributes', $items);
     }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/GridPageAction.php
similarity index 88%
rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product.php
rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/GridPageAction.php
index 611c058c430b746b066c880efb99184c0981f397..8ffaeae30cbe66610317f56b74cfd19123868ff9 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/GridPageAction.php
@@ -22,17 +22,16 @@
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
 
-namespace Magento\Catalog\Test\Block\Adminhtml;
+namespace Magento\Catalog\Test\Block\Adminhtml\Product;
 
-use Mtf\Block\Block;
+use Magento\Backend\Test\Block\GridPageActions as ParentGridPageActions;
 use Mtf\Client\Element\Locator;
 
 /**
- * Class Product
+ * Class GridPageAction
  * Catalog manage products block
- *
  */
-class Product extends Block
+class GridPageAction extends ParentGridPageActions
 {
     /**
      * Product toggle button
@@ -52,6 +51,7 @@ class Product extends Block
      * Add product using split button
      *
      * @param string $productType
+     * @return void
      */
     public function addProduct($productType = 'simple')
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php
index 5f54bf33a3f7093d04a56ceac5a4399183d75c18..f2ab98df6df055c71d864c3a6bcfd542068df5aa 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php
@@ -24,15 +24,12 @@
 
 namespace Magento\Catalog\Test\Block\Adminhtml\Product;
 
+use Magento\Backend\Test\Block\Widget\FormTabs;
 use Mtf\Client\Element;
-use Mtf\Factory\Factory;
-use Mtf\Client\Element\Locator;
 use Mtf\Fixture\FixtureInterface;
 use Mtf\Fixture\InjectableFixture;
 use Magento\Catalog\Test\Fixture\Product;
-use Magento\Backend\Test\Block\Widget\Tab;
-use Magento\Backend\Test\Block\Widget\FormTabs;
-use Magento\Catalog\Test\Fixture\ConfigurableProduct;
+use Mtf\Client\Element\Locator;
 use Magento\Catalog\Test\Fixture\CatalogCategory;
 use Magento\Catalog\Test\Fixture\CatalogProductAttribute;
 
@@ -43,155 +40,101 @@ use Magento\Catalog\Test\Fixture\CatalogProductAttribute;
 class ProductForm extends FormTabs
 {
     /**
-     * New variation set button selector
+     * Attribute on the Product page
      *
      * @var string
      */
-    protected $newVariationSet = '[data-ui-id="admin-product-edit-tab-super-config-grid-container-add-attribute"]';
+    protected $attribute = './/*[contains(@class,"label")]/span[text()="%s"]';
 
     /**
-     * Category name selector
+     * Attribute Search locator the Product page
      *
      * @var string
      */
-    protected $categoryName = '//*[contains(@class, "mage-suggest-choice")]/*[text()="%categoryName%"]';
+    protected $attributeSearch = '#product-attribute-search-container';
 
     /**
-     * 'Advanced Settings' tab
+     * Selector for trigger(show/hide) of advanced setting content
      *
      * @var string
      */
-    protected $advancedSettings = '#product_info_tabs-advanced [data-role="trigger"]';
+    protected $advancedSettingTrigger = '#product_info_tabs-advanced [data-role="trigger"]';
 
     /**
-     * Advanced tab list
+     * Selector for advanced setting content
      *
      * @var string
      */
-    protected $advancedTabList = '#product_info_tabs-advanced[role="tablist"]';
 
-    /**
-     * Advanced tab panel
-     *
-     * @var string
-     */
-    protected $advancedTabPanel = './/*[role="tablist"]//ul[!contains(@style,"overflow")]';
+    protected $advancedSettingContent = '#product_info_tabs-advanced [data-role="content"]';
 
     /**
-     * CSS locator button status of the product
+     * Variations Attribute Search locator the Product page
      *
      * @var string
      */
-    protected $onlineSwitcher = '#product-online-switcher%s + [for="product-online-switcher"]';
+    protected $variationsAttributeSearch = '#variations-search-field';
 
     /**
-     * Category fixture
-     *
-     * @var CatalogCategory
-     */
-    protected $category;
-
-    /**
-     * Attribute on the Product page
+     * Variations Tab locator the Product page
      *
      * @var string
      */
-    protected $attribute = './/*[contains(@class,"label")]/span[text()="%s"]';
+    protected $variationsTab = '#product_info_tabs_super_config_content .title';
 
     /**
-     * Attribute Search locator the Product page
+     * Custom Tab locator
      *
      * @var string
      */
-    protected $attributeSearch = '#product-attribute-search-container';
+    protected $customTab = './/*/a[contains(@id,"product_info_tabs_%s")]';
 
     /**
      * Fill the product form
      *
-     * @param FixtureInterface $fixture
-     * @param CatalogCategory $category
-     * @param Element $element
-     * @return $this
+     * @param FixtureInterface $product
+     * @param Element|null $element [optional]
+     * @param FixtureInterface|null $category [optional]
+     * @return FormTabs
      */
-    public function fillProduct(
-        FixtureInterface $fixture,
-        CatalogCategory $category = null,
-        Element $element = null
-    ) {
-        $this->category = $category;
-        $this->fillCategory($fixture);
+    public function fill(FixtureInterface $product, Element $element = null, FixtureInterface $category = null)
+    {
+        $tabs = $this->getFieldsByTabs($product);
 
-        if ($fixture instanceof InjectableFixture) {
-            $status = $fixture->getStatus();
-            if (($status === 'Product offline'
-                    && $this->_rootElement->find(sprintf($this->onlineSwitcher, ':checked'))->isVisible())
-                || ($status === 'Product online'
-                    && $this->_rootElement->find(sprintf($this->onlineSwitcher, ':not(:checked)'))->isVisible())
-            ) {
-                $this->_rootElement->find(sprintf($this->onlineSwitcher, ''))->click();
-            }
+        if ($category) {
+            $tabs['product-details']['category_ids']['value'] = ($category instanceof InjectableFixture )
+                ? $category->getName()
+                : $category->getCategoryName();
         }
 
-        return parent::fill($fixture, $element);
+        $this->showAdvancedSettings();
+        return parent::fillTabs($tabs, $element);
     }
 
     /**
-     * Select category
+     * Get data of the tabs
      *
-     * @param FixtureInterface $fixture
-     * @return void|null
+     * @param FixtureInterface|null $fixture
+     * @param Element|null $element
+     * @return array
      */
-    protected function fillCategory(FixtureInterface $fixture)
+    public function getData(FixtureInterface $fixture = null, Element $element = null)
     {
-        // TODO should be removed after suggest widget implementation as typified element
-        $categoryName = null;
-        if (!empty($this->category)) {
-            $categoryName = $this->category->getName();
-        }
-        if (empty($categoryName) && !($fixture instanceof InjectableFixture)) {
-            $categoryName = $fixture->getCategoryName();
-        }
-        if (empty($categoryName)) {
-            return;
-        }
-
-        $category = $this->_rootElement->find(
-            str_replace(
-                '%categoryName%',
-                $categoryName,
-                $this->categoryName
-            ),
-            Locator::SELECTOR_XPATH
-        );
-        if (!$category->isVisible()) {
-            $this->fillCategoryField(
-                $categoryName,
-                'category_ids-suggest',
-                '//*[@id="attribute-category_ids-container"]'
-            );
-        }
+        $this->showAdvancedSettings();
+        return parent::getData($fixture, $element);
     }
 
     /**
-     * Fills select category field
+     * Show Advanced Setting
      *
-     * @param string $name
-     * @param string $elementId
-     * @param string $parentLocation
      * @return void
      */
-    protected function fillCategoryField($name, $elementId, $parentLocation)
+    protected function showAdvancedSettings()
     {
-        // TODO should be removed after suggest widget implementation as typified element
-        $this->_rootElement->find($elementId, Locator::SELECTOR_ID)->setValue($name);
-        $this->waitForElementVisible(
-            $parentLocation . '//div[@class="mage-suggest-dropdown"]',
-            Locator::SELECTOR_XPATH
-        );
-        $this->_rootElement->find(
-            $parentLocation . '//li[contains(@data-suggest-option, \'"label":"' . $name . '",\')]//a',
-            Locator::SELECTOR_XPATH
-        )->click();
+        if (!$this->_rootElement->find($this->advancedSettingContent)->isVisible()) {
+            $this->_rootElement->find($this->advancedSettingTrigger)->click();
+            $this->waitForElementVisible($this->advancedSettingContent);
+        }
     }
 
     /**
@@ -252,80 +195,6 @@ class ProductForm extends FormTabs
         $this->waitForElementVisible('input#new_category_name');
     }
 
-    /**
-     * Open tab
-     *
-     * @param string $tabName
-     * @return Tab|bool
-     */
-    public function openTab($tabName)
-    {
-        $rootElement = $this->_rootElement;
-        $selector = $this->tabs[$tabName]['selector'];
-        $strategy = isset($this->tabs[$tabName]['strategy'])
-            ? $this->tabs[$tabName]['strategy']
-            : Locator::SELECTOR_CSS;
-        $tab = $this->_rootElement->find($selector, $strategy);
-        $advancedSettings = $this->_rootElement->find($this->advancedSettings);
-
-        // Wait until all tabs will load
-        $advancedTabList = $this->advancedTabList;
-        $this->_rootElement->waitUntil(
-            function () use ($rootElement, $advancedTabList) {
-                return $rootElement->find($advancedTabList)->isVisible();
-            }
-        );
-
-        if ($tab->isVisible()) {
-            $tab->click();
-        } elseif ($advancedSettings->isVisible()) {
-            $advancedSettings->click();
-            // Wait for open tab animation
-            $tabPanel = $this->advancedTabPanel;
-            $this->_rootElement->waitUntil(
-                function () use ($rootElement, $tabPanel) {
-                    return $rootElement->find($tabPanel, Locator::SELECTOR_XPATH)->isVisible();
-                }
-            );
-            // Wait until needed tab will appear
-            $this->_rootElement->waitUntil(
-                function () use ($rootElement, $selector, $strategy, $tabPanel) {
-                    $this->_rootElement->waitUntil(
-                        function () use ($rootElement, $tabPanel) {
-                            return $rootElement->find($tabPanel, Locator::SELECTOR_XPATH)->isVisible();
-                        }
-                    );
-                    return $rootElement->find($selector, $strategy)->isVisible();
-                }
-            );
-            $tab->click();
-        } else {
-            return false;
-        }
-
-        return $this;
-    }
-
-    /**
-     * Get data of the tabs
-     *
-     * @param FixtureInterface|null $fixture
-     * @param Element|null $element
-     * @return array
-     */
-    public function getData(FixtureInterface $fixture = null, Element $element = null)
-    {
-        $data = parent::getData($fixture);
-        if ($fixture->hasData('status')) {
-            $data['status'] = 'Product offline';
-            if ($this->_rootElement->find(sprintf($this->onlineSwitcher, ':checked'))->isVisible()) {
-                $data['status'] = 'Product online';
-            }
-        }
-
-        return $data;
-    }
-
     /**
      * Check visibility of the attribute on the product page
      *
@@ -348,7 +217,7 @@ class ProductForm extends FormTabs
      * @param CatalogProductAttribute $productAttribute
      * @return bool
      */
-    public function checkAttributeInSearchAttributeForm($productAttribute)
+    public function checkAttributeInSearchAttributeForm(CatalogProductAttribute $productAttribute)
     {
         return $this->_rootElement->find(
             $this->attributeSearch,
@@ -356,4 +225,56 @@ class ProductForm extends FormTabs
             'Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Attributes\Search'
         )->isExistAttributeInSearchResult($productAttribute);
     }
+
+    /**
+     * Call method that checking present attribute in search result
+     *
+     * @param CatalogProductAttribute $productAttribute
+     * @return bool
+     */
+    public function checkAttributeInVariationsSearchAttributeForm(CatalogProductAttribute $productAttribute)
+    {
+        return $this->_rootElement->find(
+            $this->variationsAttributeSearch,
+            Locator::SELECTOR_CSS,
+            'Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Search'
+        )->isExistAttributeInSearchResult($productAttribute);
+    }
+
+    /**
+     * Open Variations tab on Product form
+     *
+     * @return void
+     */
+    public function openVariationsTab()
+    {
+        if (!$this->_rootElement->find($this->variationsAttributeSearch, Locator::SELECTOR_CSS)->isVisible()) {
+            $this->_rootElement->find($this->variationsTab, Locator::SELECTOR_CSS)->click();
+        }
+    }
+
+    /**
+     * Check tab visibility on Product form
+     *
+     * @param string $tabName
+     * @return bool
+     */
+    public function isTabVisible($tabName)
+    {
+        $tabName = strtolower($tabName);
+
+        return $this->_rootElement->find(sprintf($this->customTab, $tabName), Locator::SELECTOR_XPATH)->isVisible();
+    }
+
+    /**
+     * Open custom tab on Product form
+     *
+     * @param string $tabName
+     * @return void
+     */
+    public function openCustomTab($tabName)
+    {
+        $tabName = strtolower($tabName);
+        $this->_rootElement->find(sprintf($this->customTab, $tabName), Locator::SELECTOR_XPATH)->click();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml
index 8e443f1eac124d5569eaa26a34c87aab6b3548a3..56f08f31376a55ae9506bfa17c54931e57cfdd3b 100755
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml
@@ -29,35 +29,40 @@
         <selector>#product_info_tabs_product-details</selector>
         <strategy>css selector</strategy>
         <wrapper>product</wrapper>
-            <fields>
-                <attribute_set_id>
-                    <selector>#product-template-suggest-container</selector>
-                    <class>Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\ProductDetails\AttributeSet</class>
-                </attribute_set_id>
-                <attribute_id>
-                    <selector>#product-attribute-search-container</selector>
-                    <class>Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Attributes\Search</class>
-                </attribute_id>
-                <tax_class_id>
+        <fields>
+            <status>
+                <selector>.product-actions .switcher</selector>
+                <class>Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\ProductDetails\ProductOnlineSwitcher</class>
+            </status>
+            <attribute_set_id>
+                <selector>#product-template-suggest-container</selector>
+                <class>Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\ProductDetails\AttributeSet</class>
+            </attribute_set_id>
+            <attribute_id>
+                <selector>#product-attribute-search-container</selector>
+                <class>Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Attributes\Search</class>
+            </attribute_id>
+            <tax_class_id>
+                <input>select</input>
+            </tax_class_id>
+            <is_virtual>
+                <input>checkbox</input>
+            </is_virtual>
+            <category_ids>
+                <selector>#attribute-category_ids-container</selector>
+                <class>Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\ProductDetails\CategoryIds</class>
+            </category_ids>
+            <quantity_and_stock_status composite="1">
+                <qty>
+                    <selector>[name="product[quantity_and_stock_status][qty]"]</selector>
+                </qty>
+                <is_in_stock>
+                    <selector>[name="product[quantity_and_stock_status][is_in_stock]"]</selector>
                     <input>select</input>
-                </tax_class_id>
-                <is_virtual>
-                    <input>checkbox</input>
-                </is_virtual>
-                <quantity_and_stock_status composite="1">
-                    <qty>
-                        <selector>#qty</selector>
-                    </qty>
-                    <is_in_stock>
-                        <selector>#quantity_and_stock_status</selector>
-                        <input>select</input>
-                    </is_in_stock>
-                </quantity_and_stock_status>
-                <description>
-                    <selector>#description</selector>
-                    <input>textarea</input>
-                </description>
-            </fields>
+                </is_in_stock>
+            </quantity_and_stock_status>
+            <description />
+        </fields>
     </product-details>
     <websites>
         <class>\Magento\Backend\Test\Block\Widget\Tab</class>
@@ -66,8 +71,8 @@
         <wrapper>product</wrapper>
         <fields>
             <website_ids>
-                <selector>[name='product[website_ids][]']</selector>
-                <input>checkbox</input>
+                <selector>#product_info_tabs_websites_content .store-tree</selector>
+                <class>\Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Websites\StoreTree</class>
             </website_ids>
         </fields>
     </websites>
@@ -88,20 +93,25 @@
         <strategy>css selector</strategy>
         <wrapper>product[stock_data]</wrapper>
         <fields>
-            <inventory_manage_stock>
-                <selector>[name='product[stock_data][manage_stock]']</selector>
-                <input>select</input>
-            </inventory_manage_stock>
-            <inventory_qty>
-                <selector>[name='product[stock_data][qty]']</selector>
-            </inventory_qty>
-            <stock_data_use_config_min_qty>
-                <selector>[name='product[stock_data][use_config_min_qty]']</selector>
-                <input>checkbox</input>
-            </stock_data_use_config_min_qty>
-            <stock_data_min_qty>
-                <selector>[name='product[stock_data][min_qty]']</selector>
-            </stock_data_min_qty>
+            <stock_data composite="1">
+                <manage_stock>
+                    <selector>[name='product[stock_data][manage_stock]']</selector>
+                    <input>select</input>
+                </manage_stock>
+                <qty>
+                    <selector>[name='product[stock_data][qty]']</selector>
+                </qty>
+                <use_config_min_qty>
+                    <selector>[name='product[stock_data][use_config_min_qty]']</selector>
+                    <input>checkbox</input>
+                </use_config_min_qty>
+                <min_qty>
+                    <selector>[name='product[stock_data][min_qty]']</selector>
+                </min_qty>
+                <use_config_manage_stock>
+                    <input>checkbox</input>
+                </use_config_manage_stock>
+            </stock_data>
         </fields>
     </advanced-inventory>
     <autosettings>
@@ -117,7 +127,16 @@
                 <selector>#short_description</selector>
                 <input>textarea</input>
             </short_description>
-            <url_key></url_key>
+            <is_returnable>
+                <input>select</input>
+            </is_returnable>
+            <url_key/>
+            <gift_message_available>
+                <input>select</input>
+            </gift_message_available>
+            <use_config_gift_message_available>
+                <input>checkbox</input>
+            </use_config_gift_message_available>
         </fields>
     </autosettings>
     <variations>
@@ -131,7 +150,7 @@
         <strategy>css selector</strategy>
     </grouped-product>
     <customer-options>
-        <class>\Magento\Catalog\Test\Block\Adminhtml\Product\Edit\CustomOptionsTab</class>
+        <class>\Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options</class>
         <selector>#product_info_tabs_customer_options</selector>
         <strategy>css selector</strategy>
         <fields>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Widget/Chooser.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Widget/Chooser.php
new file mode 100644
index 0000000000000000000000000000000000000000..1dbd80cdc3310625889e479421baaa6eed9a2ee4
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Widget/Chooser.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Widget;
+
+use Magento\Backend\Test\Block\Widget\Grid;
+
+/**
+ * Class Chooser
+ * Backend Cms Page select product grid
+ */
+class Chooser extends Grid
+{
+    /**
+     * Filters array mapping
+     *
+     * @var array
+     */
+    protected $filters = [
+        'chooser_sku' => [
+            'selector' => 'input[name="chooser_sku"]'
+        ],
+    ];
+
+    /**
+     * Locator value for link in sku column
+     *
+     * @var string
+     */
+    protected $editLink = 'td.col-sku';
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Backend/ProductForm.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Backend/ProductForm.xml
index 6de3916287afa53d7e5824ba16519d4efb46ed72..8e7c8113ab29e46632ec0e49dc909ee001958d91 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Backend/ProductForm.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Backend/ProductForm.xml
@@ -111,7 +111,7 @@
         <strategy>css selector</strategy>
     </grouped-product>
     <customer-options>
-        <class>\Magento\Catalog\Test\Block\Adminhtml\Product\Edit\CustomOptionsTab</class>
+        <class>\Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options</class>
         <selector>#product_info_tabs_customer_options</selector>
         <strategy>css selector</strategy>
         <fields>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Category/View.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Category/View.php
old mode 100644
new mode 100755
index 4b5a13b3108cd8580889792bef6c2ec751220969..b056a546fb3ca27d7c18243844391d7f8ac4c70d
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Category/View.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Category/View.php
@@ -37,7 +37,7 @@ class View extends Block
      *
      * @var string
      */
-    protected $description = '.category.description';
+    protected $description = '.category-description';
 
     /**
      * Get description
@@ -48,4 +48,14 @@ class View extends Block
     {
         return $this->_rootElement->find($this->description)->getText();
     }
+
+    /**
+     * Get Category Content
+     *
+     * @return string
+     */
+    public function getContent()
+    {
+        return $this->_rootElement->getText();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/ListCompare.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/ListCompare.php
new file mode 100644
index 0000000000000000000000000000000000000000..98cfd200d72d1f45ba87d06e3c9d543cf9b7ba8b
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/ListCompare.php
@@ -0,0 +1,218 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Product\Compare;
+
+use Mtf\Block\Block;
+use Mtf\Client\Element;
+use Mtf\Client\Element\Locator;
+
+/**
+ * Class ListCompare
+ * Compare list product block
+ */
+class ListCompare extends Block
+{
+    /**
+     * Selector by product info
+     *
+     * @var string
+     */
+    protected $productInfo = '//td[contains(@class, "cell product info")][%d]';
+
+    /**
+     * Selector by product attribute
+     *
+     * @var string
+     */
+    protected $productAttribute = '//tr[th//*[normalize-space(text()) = "%s"]]';
+
+    /**
+     * Selector by name product
+     *
+     * @var string
+     */
+    protected $nameSelector = './/*[contains(@class, "product name")]/a';
+
+    /**
+     * Selector for search product via name
+     *
+     * @var string
+     */
+    protected $productName = '[normalize-space(text()) = "%s"]';
+
+    /**
+     * Selector by price product
+     *
+     * @var string
+     */
+    protected $priceSelector = './/div[contains(@class,"price-box")]';
+
+    /**
+     * Selector by sku product
+     *
+     * @var string
+     */
+    protected $attributeSelector = './td[%d]/div';
+
+    /**
+     * Remove button selector
+     *
+     * @var string
+     */
+    protected $removeButton = './/thead//td[%d]//a[contains(@class,"action delete")]';
+
+    /**
+     * Selector for empty message
+     *
+     * @var string
+     */
+    protected $isEmpty = 'p.empty';
+
+    /**
+     * Get product info
+     *
+     * @param int $index
+     * @param string $attributeKey
+     * @param string $currency
+     * @return string
+     */
+    public function getProductInfo($index, $attributeKey, $currency = ' $')
+    {
+        $infoBlock = $this->getCompareProductInfo($index);
+        if ($attributeKey == 'price') {
+            $price = $infoBlock->find($this->priceSelector, Locator::SELECTOR_XPATH)->getText();
+            preg_match_all('`([a-z]+).*?([\d\.]+)`i', $price, $prices);
+            if (!empty($prices[0])) {
+                $resultPrice = [];
+                foreach ($prices[1] as $key => $value) {
+                    $resultPrice['price_' . lcfirst($value)] = $prices[2][$key];
+                }
+                return $resultPrice;
+            }
+            return trim($price, $currency);
+        } else {
+            return $infoBlock->find($this->nameSelector, Locator::SELECTOR_XPATH)->getText();
+        }
+    }
+
+    /**
+     * Get item compare product info
+     *
+     * @param int $index
+     * @return Element
+     */
+    protected function getCompareProductInfo($index)
+    {
+        return $this->_rootElement->find(sprintf($this->productInfo, $index), Locator::SELECTOR_XPATH);
+    }
+
+    /**
+     * Get item compare product attribute
+     *
+     * @param string $key
+     * @return Element
+     */
+    protected function getCompareProductAttribute($key)
+    {
+        return $this->_rootElement->find(sprintf($this->productAttribute, $key), Locator::SELECTOR_XPATH);
+    }
+
+    /**
+     * Get item attribute
+     *
+     * @param int $indexProduct
+     * @param string $attributeKey
+     * @return string
+     */
+    public function getProductAttribute($indexProduct, $attributeKey)
+    {
+        return trim(
+            $this->getCompareProductAttribute($attributeKey)
+                ->find(sprintf($this->attributeSelector, $indexProduct), Locator::SELECTOR_XPATH)->getText()
+        );
+    }
+
+    /**
+     * Remove product from compare product list
+     *
+     * @param int $index [optional]
+     * @return void
+     */
+    public function removeProduct($index = 1)
+    {
+        $this->_rootElement->find(sprintf($this->removeButton, $index), Locator::SELECTOR_XPATH)->click();
+    }
+
+    /**
+     * Remove all products from compare product list
+     *
+     * @return void
+     */
+    public function removeAllProducts()
+    {
+        while ($this->isProductVisible()) {
+            $this->removeProduct();
+            $this->reinitRootElement();
+        }
+    }
+
+    /**
+     * Visible product in compare product list
+     *
+     * @param int $index [optional]
+     * @return bool
+     */
+    public function isProductVisible($index = 1)
+    {
+        return $this->_rootElement->find(sprintf($this->removeButton, $index), Locator::SELECTOR_XPATH)->isVisible();
+    }
+
+    /**
+     * Verify product is visible in compare product block
+     *
+     * @param string $productName
+     * @return bool
+     */
+    public function isProductVisibleInCompareBlock($productName = '')
+    {
+        $nameSelector = $this->nameSelector . sprintf($this->productName, $productName);
+        return $this->_rootElement->find($nameSelector, Locator::SELECTOR_XPATH)->isVisible();
+    }
+
+    /**
+     * Get empty message on compare product block
+     * Returns message absence of compared products or false, if the message isn't visible
+     *
+     * @return string|bool
+     */
+    public function getEmptyMessage()
+    {
+        $isEmpty = $this->_rootElement->find($this->isEmpty);
+        if ($isEmpty->isVisible()) {
+            return $isEmpty->getText();
+        }
+        return false;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/Sidebar.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/Sidebar.php
new file mode 100644
index 0000000000000000000000000000000000000000..fc668a01879fd0e7433f0949aec5c100ada6ad00
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/Sidebar.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Block\Product\Compare;
+
+use Mtf\Client\Element;
+
+/**
+ * Class Sidebar
+ * Compare product block on cms page
+ */
+class Sidebar extends ListCompare
+{
+    /**
+     * Selector for empty message
+     *
+     * @var string
+     */
+    protected $isEmpty = 'p.empty';
+
+    /**
+     * Product name selector
+     *
+     * @var string
+     */
+    protected $productName = 'li.item.odd.last strong.name a';
+
+    /**
+     * Selector for "Clear All" button
+     *
+     * @var string
+     */
+    protected $clearAll = '#compare-clear-all';
+
+    /**
+     * Get compare products block content
+     *
+     * @return array|string
+     */
+    public function getProducts()
+    {
+        $result = [];
+        $isEmpty = $this->_rootElement->find($this->isEmpty);
+        if ($isEmpty->isVisible()) {
+            return $isEmpty->getText();
+        }
+        $elements = $this->_rootElement->find($this->productName)->getElements();
+        foreach ($elements as $element) {
+            $result[] = $element->getText();
+        }
+        return $result;
+    }
+
+    /**
+     * Click "Clear All" on "My Account" page
+     *
+     * @return void
+     */
+    public function clickClearAll()
+    {
+        $this->_rootElement->find($this->clearAll)->click();
+        $this->_rootElement->acceptAlert();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Price.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Price.php
old mode 100644
new mode 100755
index 0b5c6aead82ba111c50544bdd989f7711f67bd25..726ec183155570c7b02cb80f0f011ca27272187e
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Price.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Price.php
@@ -65,7 +65,7 @@ class Price extends Block
      *
      * @var string
      */
-    protected $priceMap = '.old.price .price';
+    protected $priceMap = '.old.price .price .price';
 
     /**
      * Actual Price
@@ -113,6 +113,7 @@ class Price extends Block
         //@TODO it have to rewrite when will be possibility to divide it to different blocks(by product type)
         $prices = explode("\n", trim($this->_rootElement->getText()));
         if (count($prices) === 1) {
+            $prices[0] = str_replace(',', '', $prices[0]);
             return ['price_regular_price' => trim($prices[0], $currency)];
         }
         return $this->formatPricesData($prices, $currency);
@@ -131,7 +132,7 @@ class Price extends Block
         foreach ($prices as $price) {
             list($name, $price) = explode($currency, $price);
             $name = str_replace(' ', '_', trim(preg_replace('#[^0-9a-z]+#i', ' ', strtolower($name)), ' '));
-            $formatted['price_' . $name] = $price;
+            $formatted['price_' . $name] = str_replace(',', '', $price);
         }
         return $formatted;
     }
@@ -259,20 +260,22 @@ class Price extends Block
     /**
      * Get price from
      *
-     * @return array|string
+     * @param string $currency
+     * @return string
      */
-    public function getPriceFrom()
+    public function getPriceFrom($currency = '$')
     {
-        return $this->_rootElement->find($this->priceFromSelector)->getText();
+        return trim($this->_rootElement->find($this->priceFromSelector)->getText(), $currency);
     }
 
     /**
      * Get price to
      *
-     * @return array|string
+     * @param string $currency
+     * @return string
      */
-    public function getPriceTo()
+    public function getPriceTo($currency = '$')
     {
-        return $this->_rootElement->find($this->priceToSelector)->getText();
+        return trim($this->_rootElement->find($this->priceToSelector)->getText(), $currency);
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View.php
index 627382ba707a7438fe2dcc516fd20b227f63cd71..6b984e17225a0c183e6a3366215f6e1f1832f37b 100755
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View.php
@@ -34,9 +34,19 @@ use Magento\Catalog\Test\Fixture\ConfigurableProduct;
 /**
  * Class View
  * Product view block on the product page
+ *
+ * @SuppressWarnings(PHPMD.TooManyFields)
+ * @SuppressWarnings(PHPMD.ExcessivePublicCount)
  */
 class View extends Block
 {
+    /**
+     * Custom options CSS selector
+     *
+     * @var string
+     */
+    protected $customOptionsSelector = '.product-options-wrapper';
+
     /**
      * 'Add to Cart' button
      *
@@ -70,7 +80,7 @@ class View extends Block
      *
      * @var string
      */
-    protected $productName = '.page-title.product span';
+    protected $productName = '.page-title.product h1.title .base';
 
     /**
      * Product sku element
@@ -142,6 +152,20 @@ class View extends Block
      */
     protected $tierPricesSelector = "//ul[contains(@class,'tier')]//*[@class='item'][%line-number%]";
 
+    /**
+     * Selector for price block
+     *
+     * @var string
+     */
+    protected $priceBlock = '.product-info-main .price-box';
+
+    /**
+     * 'Add to Compare' button
+     *
+     * @var string
+     */
+    protected $clickAddToCompare = '.action.tocompare';
+
     /**
      * Get bundle options block
      *
@@ -161,9 +185,7 @@ class View extends Block
      */
     protected function getPriceBlock()
     {
-        return Factory::getBlockFactory()->getMagentoCatalogProductPrice(
-            $this->_rootElement->find('.product-info-main .price-box')
-        );
+        return Factory::getBlockFactory()->getMagentoCatalogProductPrice($this->_rootElement->find($this->priceBlock));
     }
 
     /**
@@ -263,6 +285,19 @@ class View extends Block
         );
     }
 
+    /**
+     * This method returns the custom options block.
+     *
+     * @return \Magento\Catalog\Test\Block\Product\View\CustomOptions
+     */
+    public function getCustomOptionsBlock()
+    {
+        return $this->blockFactory->create(
+            'Magento\Catalog\Test\Block\Product\View\CustomOptions',
+            ['element' => $this->_rootElement->find($this->customOptionsSelector)]
+        );
+    }
+
     /**
      * Return product price displayed on page
      *
@@ -358,14 +393,14 @@ class View extends Block
         }
         if ($configureSection->isVisible()) {
             $productOptions = $product->getProductOptions();
-            $this->getBundleBlock()->fillProductOptions($productOptions);
+            $this->getCustomOptionsBlock()->fillProductOptions($productOptions);
         }
     }
 
     /**
      * This method return array tier prices
      *
-     * @param int $lineNumber
+     * @param int $lineNumber [optional]
      * @return array
      */
     public function getTierPrices($lineNumber = 1)
@@ -384,7 +419,7 @@ class View extends Block
     public function clickCustomize()
     {
         $this->_rootElement->find($this->customizeButton)->click();
-
+        $this->waitForElementVisible($this->addToCart);
     }
 
     /**
@@ -445,6 +480,16 @@ class View extends Block
      */
     public function stockAvailability()
     {
-        return $this->_rootElement->find($this->stockAvailability)->getText();
+        return strtolower($this->_rootElement->find($this->stockAvailability)->getText());
+    }
+
+    /**
+     * Click "Add to Compare" button
+     *
+     * @return void
+     */
+    public function clickAddToCompare()
+    {
+        $this->_rootElement->find($this->clickAddToCompare, Locator::SELECTOR_CSS)->click();
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php
old mode 100644
new mode 100755
index 3d80fabc9215167f0e1a7683a10513de386f90b3..af6f96cb6677275f238d29a78dac5ec439e07008
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php
@@ -24,73 +24,86 @@
 
 namespace Magento\Catalog\Test\Block\Product\View;
 
-use Mtf\Block\Block;
+use Mtf\Block\Form;
 use Mtf\Client\Element;
 use Mtf\Client\Element\Locator;
+use Mtf\Fixture\FixtureInterface;
 
 /**
  * Class Custom Options
- * Block of custom options product
- *
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+ * Form of custom options product
  */
-class CustomOptions extends Block
+class CustomOptions extends Form
 {
     /**
-     * Regexp price pattern
+     * Selector for options context
+     *
+     * @var string
+     */
+    protected $optionsContext = '#product-options-wrapper > fieldset';
+
+    /**
+     * Selector for single option block
+     *
+     * @var string
+     */
+    protected $optionElement = './div[contains(@class,"field")][%d]';
+
+    /**
+     * Selector for title of option
      *
      * @var string
      */
-    protected $pricePattern = '#\$([\d,]+\.\d+)$#';
+    protected $title = './label/span[1]';
 
     /**
-     * Field set XPath locator
+     * Selector for required option
      *
      * @var string
      */
-    protected $fieldsetLocator = '//*[@id="product-options-wrapper"]//*[@class="fieldset"]';
+    protected $required = './self::*[contains(@class,"required")]';
 
     /**
-     * Field XPath locator
+     * Selector for price notice of option
      *
      * @var string
      */
-    protected $fieldLocator = '/div[not(contains(@class,"downloads")) and contains(@class,"field")%s][%d]';
+    protected $priceNotice = './/*[@class="price-notice"]';
 
     /**
-     * Required field XPath locator
+     * Selector for max characters of option
      *
      * @var string
      */
-    protected $requiredLocator = ' and contains(@class,"required")';
+    protected $maxCharacters = './/div[@class="control"]/p[@class="note"]/strong';
 
     /**
-     * Select field XPath locator
+     * Selector for label of option value element
      *
      * @var string
      */
-    protected $selectLocator = './div[contains(@class,"control")]//select';
+    protected $optionLabel = './/div[@class="control"]//label[contains(@for, "options_")][%d]';
 
     /**
-     * Title value CSS locator
+     * Select note of option by number
      *
      * @var string
      */
-    protected $titleLocator = '.label span:not(.price-notice)';
+    protected $noteByNumber = './/*[@class="note"][%d]/strong';
 
     /**
-     * Price value CSS locator
+     * Selector for select element of option
      *
      * @var string
      */
-    protected $priceLocator = '.label .price-notice';
+    protected $selectOption = './/div[@class="control"]/select';
 
     /**
-     * Option XPath locator
+     * Selector for option of select element
      *
      * @var string
      */
-    protected $optionLocator = './option[%d]';
+    protected $option = './/option[%d]';
 
     /**
      * Option XPath locator by value
@@ -107,68 +120,302 @@ class CustomOptions extends Block
     protected $selectByTitleLocator = '//*[*[@class="product-options-wrapper"]//span[text()="%s"]]//select';
 
     /**
-     * Bundle field CSS locator
+     * Select XPath locator by option name
      *
      * @var string
      */
-    protected $bundleFieldLocator = '#product-options-wrapper > .fieldset > .field';
+    protected $optionByName = '//*[label//span[contains(.,"%s")]]';
 
     /**
      * Get product options
      *
+     * @param FixtureInterface|null $product [optional]
      * @return array
+     * @throws \Exception
      */
-    public function getOptions()
+    public function getOptions(FixtureInterface $product = null)
     {
-        $options = [];
-        $index = 1;
+        $dataOptions = ($product && $product->hasData('custom_options')) ? $product->getCustomOptions() : [];
+        $listCustomOptions = $this->getListCustomOptions();
+        $readyOptions = [];
+        $result = [];
 
-        $fieldElement = $this->_rootElement->find(
-            $this->fieldsetLocator . sprintf($this->fieldLocator, '', $index),
-            Locator::SELECTOR_XPATH
-        );
-
-        while ($fieldElement && $fieldElement->isVisible()) {
-            $option = ['price' => []];
-            $option['is_require'] = $this->_rootElement->find(
-                $this->fieldsetLocator . sprintf($this->fieldLocator, $this->requiredLocator, $index),
-                Locator::SELECTOR_XPATH
-            )->isVisible();
-            $option['title'] = $fieldElement->find($this->titleLocator)->getText();
-
-            if (($price = $fieldElement->find($this->priceLocator))
-                && $price->isVisible()
-            ) {
-                $matches = [];
-                $value = $price->getText();
-                if (preg_match($this->pricePattern, $value, $matches)) {
-                    $option['value'][] = $value;
-                    $option['price'][] = $matches[1];
-                }
-            } elseif (($prices = $fieldElement->find($this->selectLocator, Locator::SELECTOR_XPATH))
-                && $prices->isVisible()
-            ) {
-                $priceIndex = 0;
-                while (($price = $prices->find(sprintf($this->optionLocator, ++$priceIndex), Locator::SELECTOR_XPATH))
-                    && $price->isVisible()
-                ) {
-                    $matches = [];
-                    $value = $price->getText();
-                    if (preg_match($this->pricePattern, $value, $matches)) {
-                        $option['value'][] = $value;
-                        $option['price'][] = $matches[1];
-                    }
-                }
+        foreach ($dataOptions as $option) {
+            $title = $option['title'];
+            if (!isset($listCustomOptions[$title])) {
+                throw new \Exception("Can't find option: \"{$title}\"");
             }
-            $options[$option['title']] = $option;
-            ++$index;
-            $fieldElement = $this->_rootElement->find(
-                $this->fieldsetLocator . sprintf($this->fieldLocator, '', $index),
-                Locator::SELECTOR_XPATH
-            );
+
+            /** @var Element $optionElement */
+            $optionElement = $listCustomOptions[$title];
+            $typeMethod = preg_replace('/[^a-zA-Z]/', '', $option['type']);
+            $getTypeData = 'get' . ucfirst(strtolower($typeMethod)) . 'Data';
+
+            $optionData = $this->$getTypeData($optionElement);
+            $optionData['title'] = $title;
+            $optionData['type'] = $option['type'];
+            $optionData['is_require'] = $optionElement->find($this->required, Locator::SELECTOR_XPATH)->isVisible()
+                ? 'Yes'
+                : 'No';
+
+            $readyOptions[] = $title;
+            $result[$title] = $optionData;
+        }
+
+        $unreadyCustomOptions = array_diff_key($listCustomOptions, array_flip($readyOptions));
+        foreach ($unreadyCustomOptions as $optionElement) {
+            $title = $optionElement->find($this->title, Locator::SELECTOR_XPATH)->getText();
+            $result[$title] = ['title' => $title];
+        }
+
+        return $result;
+    }
+
+    /**
+     * Get list custom options
+     *
+     * @return array
+     */
+    protected function getListCustomOptions()
+    {
+        $customOptions = [];
+        $context = $this->_rootElement->find($this->optionsContext);
+
+        $count = 1;
+        $optionElement = $context->find(sprintf($this->optionElement, $count), Locator::SELECTOR_XPATH);
+        while ($optionElement->isVisible()) {
+            $title = $optionElement->find($this->title, Locator::SELECTOR_XPATH)->getText();
+            $customOptions[$title] = $optionElement;
+            ++$count;
+            $optionElement = $context->find(sprintf($this->optionElement, $count), Locator::SELECTOR_XPATH);
+        }
+        return $customOptions;
+    }
+
+    /**
+     * Get data of "Field" custom option
+     *
+     * @param Element $option
+     * @return array
+     */
+    protected function getFieldData(Element $option)
+    {
+        $price = $this->getOptionPriceNotice($option);
+        $maxCharacters = $option->find($this->maxCharacters, Locator::SELECTOR_XPATH);
+
+        return [
+            'options' => [
+                [
+                    'price' => floatval($price),
+                    'max_characters' => $maxCharacters->isVisible() ? $maxCharacters->getText() : null,
+                ]
+            ]
+        ];
+    }
+
+    /**
+     * Get data of "Area" custom option
+     *
+     * @param Element $option
+     * @return array
+     */
+    protected function getAreaData(Element $option)
+    {
+        return $this->getFieldData($option);
+    }
+
+    /**
+     * Get data of "File" custom option
+     *
+     * @param Element $option
+     * @return array
+     */
+    protected function getFileData(Element $option)
+    {
+        $price = $this->getOptionPriceNotice($option);
+
+        return [
+            'options' => [
+                [
+                    'price' => floatval($price),
+                    'file_extension' => $this->getOptionNotice($option, 1),
+                    'image_size_x' => preg_replace('/[^0-9]/', '', $this->getOptionNotice($option, 2)),
+                    'image_size_y' => preg_replace('/[^0-9]/', '', $this->getOptionNotice($option, 3)),
+                ]
+            ]
+        ];
+    }
+
+    /**
+     * Get data of "Drop-down" custom option
+     *
+     * @param Element $option
+     * @return array
+     */
+    protected function getDropdownData(Element $option)
+    {
+        $select = $option->find($this->selectOption, Locator::SELECTOR_XPATH, 'select');
+        // Skip "Choose option ..."(option #1)
+        return $this->getSelectOptionsData($select, 2);
+    }
+
+    /**
+     * Get data of "Multiple Select" custom option
+     *
+     * @param Element $option
+     * @return array
+     */
+    protected function getMultipleSelectData(Element $option)
+    {
+        $multiselect = $option->find($this->selectOption, Locator::SELECTOR_XPATH, 'multiselect');
+        return $this->getSelectOptionsData($multiselect, 1);
+    }
+
+    /**
+     * Get data of "Radio Buttons" custom option
+     *
+     * @param Element $option
+     * @return array
+     */
+    protected function getRadioButtonsData(Element $option)
+    {
+        $listOptions = [];
+
+        $count = 1;
+        $option = $option->find(sprintf($this->optionLabel, $count), Locator::SELECTOR_XPATH);
+        while ($option->isVisible()) {
+            $listOptions[] = $this->parseOptionText($option->getText());
+            ++$count;
+            $option = $option->find(sprintf($this->optionLabel, $count), Locator::SELECTOR_XPATH);
+        }
+
+        return [
+            'options' => $listOptions
+        ];
+    }
+
+    /**
+     * Get data of "Checkbox" custom option
+     *
+     * @param Element $option
+     * @return array
+     */
+    protected function getCheckboxData(Element $option)
+    {
+        return $this->getRadioButtonsData($option);
+    }
+
+    /**
+     * Get data of "Date" custom option
+     *
+     * @param Element $option
+     * @return array
+     */
+    protected function getDateData(Element $option)
+    {
+        $price = $this->getOptionPriceNotice($option);
+
+        return [
+            'options' => [
+                [
+                    'price' => floatval($price)
+                ]
+            ]
+        ];
+    }
+
+    /**
+     * Get data of "Date & Time" custom option
+     *
+     * @param Element $option
+     * @return array
+     */
+    protected function getDateTimeData(Element $option)
+    {
+        return $this->getDateData($option);
+    }
+
+    /**
+     * Get data of "Time" custom option
+     *
+     * @param Element $option
+     * @return array
+     */
+    protected function getTimeData(Element $option)
+    {
+        return $this->getDateData($option);
+    }
+
+    /**
+     * Get data from option of select and multiselect
+     *
+     * @param Element $element
+     * @param int $firstOption
+     * @return array
+     */
+    protected function getSelectOptionsData(Element $element, $firstOption = 1)
+    {
+        $listOptions = [];
+
+        $count = $firstOption;
+        $selectOption = $element->find(sprintf($this->option, $count), Locator::SELECTOR_XPATH);
+        while ($selectOption->isVisible()) {
+            $listOptions[] = $this->parseOptionText($selectOption->getText());
+            ++$count;
+            $selectOption = $element->find(sprintf($this->option, $count), Locator::SELECTOR_XPATH);
         }
 
-        return $options;
+        return [
+            'options' => $listOptions
+        ];
+    }
+
+    /**
+     * Get price from price-notice of custom option
+     *
+     * @param Element $option
+     * @return array
+     */
+    protected function getOptionPriceNotice(Element $option)
+    {
+        $priceNotice = $option->find($this->priceNotice, Locator::SELECTOR_XPATH);
+        if (!$priceNotice->isVisible()) {
+            return null;
+        }
+        return preg_replace('/[^0-9\.]/', '', $priceNotice->getText());
+    }
+
+    /**
+     * Get notice of option by number
+     *
+     * @param Element $option
+     * @param int $number
+     * @return mixed
+     */
+    protected function getOptionNotice(Element $option, $number)
+    {
+        $note = $option->find(sprintf($this->noteByNumber, $number), Locator::SELECTOR_XPATH);
+        return $note->isVisible() ? $note->getText() : null;
+    }
+
+    /**
+     * Parse option text to title and price
+     *
+     * @param string $optionText
+     * @return array
+     */
+    protected function parseOptionText($optionText)
+    {
+        preg_match('/\+?.([0-9.]+)$/', $optionText, $match);
+        $optionPrice = isset($match[1]) ? $match[1] : 0;
+        $optionTitle = isset($match[0])
+            ? substr($optionText, 0, strlen($optionText) - strlen($match[0]))
+            : $optionText;
+
+        return [
+            'title' => trim($optionTitle),
+            'price' => $optionPrice
+        ];
     }
 
     /**
@@ -177,7 +424,7 @@ class CustomOptions extends Block
      * @param array $productOptions
      * @return void
      */
-    public function fillProductOptions($productOptions)
+    public function fillProductOptions(array $productOptions)
     {
         foreach ($productOptions as $attributeLabel => $attributeValue) {
             $select = $this->_rootElement->find(
@@ -189,19 +436,83 @@ class CustomOptions extends Block
         }
     }
 
+    /**
+     * Fill custom options
+     *
+     * @param array $customOptions
+     * @return void
+     */
+    public function fillCustomOptions(array $customOptions)
+    {
+        $type = strtolower(preg_replace('/[^a-zA-Z]/', '', $customOptions['type']));
+        $customOptions += $this->dataMapping([$type => []]);
+
+        $isDate = $customOptions['type'] == 'Date' ||
+            $customOptions['type'] == 'Time' ||
+            $customOptions['type'] == 'Date & Time';
+        $isChecked = $customOptions['type'] == 'Checkbox' || $customOptions['type'] == 'Radio Buttons';
+
+        if ($isDate) {
+            $customOptions['value'] = explode('/', $customOptions['value'][0]);
+            $customOptions['dateSelector'] = $this->setDateTypeSelector(count($customOptions['value']));
+        }
+
+        foreach ($customOptions['value'] as $key => $attributeValue) {
+            $selector = $customOptions[$type]['selector'];
+            if ($isDate) {
+                $selector .= $customOptions['dateSelector'][$key];
+            } elseif ($isChecked) {
+                $selector = str_replace('%product_name%', $attributeValue, $selector);
+                $attributeValue = 'Yes';
+            }
+
+            $select = $this->_rootElement->find(
+                sprintf($this->optionByName, $customOptions['title']) . $selector,
+                Locator::SELECTOR_XPATH,
+                $customOptions[$type]['input']
+            );
+            $select->setValue($attributeValue);
+        }
+    }
+
+    /**
+     * Set item data type selector
+     *
+     * @param int $count
+     * @return array
+     */
+    protected function setDateTypeSelector($count)
+    {
+        $result = [];
+        $parent = '';
+        for ($i = 0; $i < $count; $i++) {
+            if (!(($i + 1) % 4)) {
+                $parent = '//span';
+            }
+            $result[$i] = $parent . '//select[' . ($i % 3 + 1) . ']';
+        }
+
+        return $result;
+    }
+
     /**
      * Choose custom option in a drop down
      *
-     * @param string $productOption
+     * @param string $title
+     * @param string|null $value [optional]
      * @return void
      */
-    public function selectProductCustomOption($productOption)
+    public function selectProductCustomOption($title, $value = null)
     {
         $select = $this->_rootElement->find(
-            sprintf($this->optionByValueLocator, $productOption),
+            sprintf($this->selectByTitleLocator, $title),
             Locator::SELECTOR_XPATH,
             'select'
         );
-        $select->setValue($productOption);
+
+        if (null === $value) {
+            $value = $select->find('.//option[@value != ""][1]', Locator::SELECTOR_XPATH)->getText();
+        }
+        $select->setValue($value);
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.xml
new file mode 100644
index 0000000000000000000000000000000000000000..44504ba1c175b32744a5ce008c4371775716c27c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <dropdown>
+            <selector>//select</selector>
+            <input>select</input>
+        </dropdown>
+        <multipleselect>
+            <selector>//select</selector>
+            <input>multiselect</input>
+        </multipleselect>
+        <checkbox>
+            <selector>//div[label[span[contains(text(), "%product_name%")]]]/input</selector>
+            <input>checkbox</input>
+        </checkbox>
+        <radiobuttons>
+            <selector>//div[label[span[contains(text(), "%product_name%")]]]/input</selector>
+            <input>checkbox</input>
+        </radiobuttons>
+        <date>
+            <selector />
+            <input>select</input>
+        </date>
+        <datetime>
+            <selector />
+            <input>select</input>
+        </datetime>
+        <time>
+            <selector />
+            <input>select</input>
+        </time>
+        <area>
+            <selector>//textarea</selector>
+        </area>
+        <file>
+            <selector>//input</selector>
+        </file>
+        <field>
+            <selector>//input</selector>
+        </field>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddToCartButtonAbsent.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddToCartButtonAbsent.php
old mode 100644
new mode 100755
index 6b2726761fd164acded86da7fa844643f79c33d2..013910c651fb755a35a331656338ca8549949f73
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddToCartButtonAbsent.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddToCartButtonAbsent.php
@@ -105,7 +105,7 @@ class AssertAddToCartButtonAbsent extends AbstractConstraint
     {
         $this->cmsIndex->open();
         $this->cmsIndex->getTopmenu()->selectCategoryByName(
-            $this->product->getCategoryIds()[0]['name']
+            $this->product->getCategoryIds()[0]
         );
         \PHPUnit_Framework_Assert::assertFalse(
             $this->catalogCategoryView->getListProductBlock()->checkAddToCardButton(),
@@ -122,7 +122,7 @@ class AssertAddToCartButtonAbsent extends AbstractConstraint
     {
         $this->cmsIndex->open();
         $this->cmsIndex->getTopmenu()->selectCategoryByName(
-            $this->product->getCategoryIds()[0]['name']
+            $this->product->getCategoryIds()[0]
         );
         $this->catalogCategoryView->getListProductBlock()->openProductViewPage($this->product->getName());
         \PHPUnit_Framework_Assert::assertFalse(
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddToCartButtonPresent.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddToCartButtonPresent.php
old mode 100644
new mode 100755
index f4ac24bc1c39d48ee8ae343699a4fdd64d520110..120e528430c64e2bbe3cc64fe96266110ad651ad
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddToCartButtonPresent.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddToCartButtonPresent.php
@@ -105,7 +105,7 @@ class AssertAddToCartButtonPresent extends AbstractConstraint
     {
         $this->cmsIndex->open();
         $this->cmsIndex->getTopmenu()->selectCategoryByName(
-            $this->product->getCategoryIds()[0]['name']
+            $this->product->getCategoryIds()[0]
         );
         \PHPUnit_Framework_Assert::assertTrue(
             $this->catalogCategoryView->getListProductBlock()->checkAddToCardButton(),
@@ -122,7 +122,7 @@ class AssertAddToCartButtonPresent extends AbstractConstraint
     {
         $this->cmsIndex->open();
         $this->cmsIndex->getTopmenu()->selectCategoryByName(
-            $this->product->getCategoryIds()[0]['name']
+            $this->product->getCategoryIds()[0]
         );
         $this->catalogCategoryView->getListProductBlock()->openProductViewPage($this->product->getName());
         \PHPUnit_Framework_Assert::assertTrue(
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCrossSellsProductsSection.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCrossSellsProductsSection.php
old mode 100644
new mode 100755
index 98f6e122ad7b079788e3a8e5fd4596bda2a47a7d..fd2acc9b17c8774c757d74b36c734137b1ec1fad
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCrossSellsProductsSection.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCrossSellsProductsSection.php
@@ -62,7 +62,7 @@ class AssertCrossSellsProductsSection extends AbstractConstraint
         CatalogProductView $catalogProductView,
         CheckoutCart $checkoutCart
     ) {
-        $categoryName = $product1->getCategoryIds()[0]['name'];
+        $categoryName = $product1->getCategoryIds()[0];
         $checkoutCart->open();
         $checkoutCart->getCartBlock()->clearShoppingCart();
         $cmsIndex->getTopmenu()->selectCategoryByName($categoryName);
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCustomOptionsOnProductPage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCustomOptionsOnProductPage.php
deleted file mode 100644
index 95e1ef295df99e7d3e467ede042777b58d11947f..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCustomOptionsOnProductPage.php
+++ /dev/null
@@ -1,128 +0,0 @@
-<?php
-/**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
- */
-
-namespace Magento\Catalog\Test\Constraint;
-
-use Mtf\Fixture\FixtureInterface;
-use Mtf\Constraint\AbstractConstraint;
-use Magento\Catalog\Test\Page\Product\CatalogProductView;
-
-/**
- * Class AssertCustomOptionsOnProductPage
- */
-class AssertCustomOptionsOnProductPage extends AbstractConstraint
-{
-    /**
-     * Constraint severeness
-     *
-     * @var string
-     */
-    protected $severeness = 'low';
-
-    /**
-     * Product fixture
-     *
-     * @var FixtureInterface
-     */
-    protected $product;
-
-    /**
-     * Assertion that commodity options are displayed correctly
-     *
-     * @param CatalogProductView $catalogProductView
-     * @param FixtureInterface $product
-     * @return void
-     */
-    public function processAssert(CatalogProductView $catalogProductView, FixtureInterface $product)
-    {
-        $this->product = $product;
-        // TODO fix initialization url for frontend page
-        // Open product view page
-        $catalogProductView->init($this->product);
-        $catalogProductView->open();
-        // Prepare data
-        $customOptions = $catalogProductView->getCustomOptionsBlock()->getOptions();
-        foreach ($customOptions as &$option) {
-            unset($option['value']);
-        }
-        unset($option);
-        $compareOptions = $this->prepareOptionArray($this->product->getCustomOptions());
-        $customOptions = $this->dataSortByKey($customOptions);
-        $compareOptions = $this->dataSortByKey($compareOptions);
-
-        \PHPUnit_Framework_Assert::assertEquals(
-            $customOptions,
-            $compareOptions,
-            'Incorrect display of custom product options on the product page.'
-        );
-    }
-
-    protected function dataSortByKey(array $data)
-    {
-        foreach ($data as &$item) {
-            ksort($item);
-        }
-        unset($item);
-        return $data;
-    }
-
-    /**
-     * Preparation options before comparing
-     *
-     * @param array $options
-     * @return array
-     */
-    protected function prepareOptionArray(array $options)
-    {
-        $result = [];
-        $productPrice = $this->product->hasData('group_price')
-            ? $this->product->getGroupPrice()[0]['price']
-            : $this->product->getPrice();
-
-        $placeholder = ['Yes' => true, 'No' => false];
-        foreach ($options as $option) {
-            $result[$option['title']]['is_require'] = $placeholder[$option['is_require']];
-            $result[$option['title']]['title'] = $option['title'];
-            $result[$option['title']]['price'] = [];
-            foreach ($option['options'] as $optionValue) {
-                if ($optionValue['price_type'] === 'Percent') {
-                    $optionValue['price'] = $productPrice / 100 * $optionValue['price'];
-                }
-                $result[$option['title']]['price'][] = number_format($optionValue['price'], 2);
-            }
-        }
-
-        return $result;
-    }
-
-    /**
-     * Returns a string representation of the object
-     *
-     * @return string
-     */
-    public function toString()
-    {
-        return 'Value of custom option on the page is correct.';
-    }
-}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertNoCrossSellsProductsSection.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertNoCrossSellsProductsSection.php
old mode 100644
new mode 100755
index f600e90898b9656a6482c5b4675f8fe4268d56e3..38a422f7f501fca09316224494e492cbb8933d9d
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertNoCrossSellsProductsSection.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertNoCrossSellsProductsSection.php
@@ -62,7 +62,7 @@ class AssertNoCrossSellsProductsSection extends AbstractConstraint
         CatalogProductView $catalogProductView,
         CheckoutCart $checkoutCart
     ) {
-        $categoryName = $product1->getCategoryIds()[0]['name'];
+        $categoryName = $product1->getCategoryIds()[0];
         $checkoutCart->open();
         $checkoutCart->getCartBlock()->clearShoppingCart();
         $cmsIndex->getTopmenu()->selectCategoryByName($categoryName);
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertNoRelatedProductsSection.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertNoRelatedProductsSection.php
old mode 100644
new mode 100755
index c722951047db2b347a7abf482e5e23bec8b7dac5..0e53a68b1334ed5a8750c67ef00da4f233eb1e95
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertNoRelatedProductsSection.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertNoRelatedProductsSection.php
@@ -59,7 +59,7 @@ class AssertNoRelatedProductsSection extends AbstractConstraint
         CatalogCategoryView $catalogCategoryView,
         CatalogProductView $catalogProductView
     ) {
-        $categoryName = $product1->getCategoryIds()[0]['name'];
+        $categoryName = $product1->getCategoryIds()[0];
         $cmsIndex->open();
         $cmsIndex->getTopmenu()->selectCategoryByName($categoryName);
         $catalogCategoryView->getListProductBlock()->openProductViewPage($product1->getName());
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertNoUpSellsProductsSection.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertNoUpSellsProductsSection.php
old mode 100644
new mode 100755
index 7aec1213cfe5a2803269d92ac82a90ca3cefc21f..8f8a952c590e7e46d68d0829319bc60e2338430f
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertNoUpSellsProductsSection.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertNoUpSellsProductsSection.php
@@ -59,7 +59,7 @@ class AssertNoUpSellsProductsSection extends AbstractConstraint
         CatalogCategoryView $catalogCategoryView,
         CatalogProductView $catalogProductView
     ) {
-        $categoryName = $product1->getCategoryIds()[0]['name'];
+        $categoryName = $product1->getCategoryIds()[0];
         $cmsIndex->open();
         $cmsIndex->getTopmenu()->selectCategoryByName($categoryName);
         $catalogCategoryView->getListProductBlock()->openProductViewPage($product1->getName());
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertPriceOnProductPageInterface.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertPriceOnProductPageInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..9447928dc4c586153ae87b70f9677ca130b72bbd
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertPriceOnProductPageInterface.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Fixture\FixtureInterface;
+use Magento\Catalog\Test\Page\Product\CatalogProductView;
+
+/**
+ * Interface AssertPriceOnProductPageInterface
+ * Interface for Constraints price on product page classes
+ */
+interface AssertPriceOnProductPageInterface
+{
+    /**
+     * Verify product price on product view page
+     *
+     * @param FixtureInterface $product
+     * @param CatalogProductView $catalogProductView
+     * @param string $block
+     * @return void
+     */
+    public function assertPrice(FixtureInterface $product, CatalogProductView $catalogProductView, $block);
+
+    /**
+     * Set $errorMessage for constraint
+     *
+     * @param string $errorMessage
+     * @return void
+     */
+    public function setErrorMessage($errorMessage);
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php
index f78a28f429825ba8f7e83693c1f84e421f7819f0..d7a7209b8e2ce384ed622aa3bbd2562e57ba5d7c 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php
@@ -58,7 +58,7 @@ class AssertProductAttributeAbsenceInSearchOnProductForm extends AbstractConstra
         CatalogProductNew $newProductPage
     ) {
         $productGrid->open();
-        $productGrid->getProductBlock()->addProduct('simple');
+        $productGrid->getGridPageActionBlock()->addProduct('simple');
         \PHPUnit_Framework_Assert::assertFalse(
             $newProductPage->getForm()->checkAttributeInSearchAttributeForm($productAttribute),
             "Product attribute found in Attribute Search form."
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInTemplateGroups.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInTemplateGroups.php
new file mode 100644
index 0000000000000000000000000000000000000000..43103300027100aed9bba1feed956717bc736616
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInTemplateGroups.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Fixture\CatalogAttributeSet;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex;
+
+/**
+ * Class AssertProductAttributeAbsenceInTemplateGroups
+ * Checks that product attribute isn't displayed in Product template's Groups section
+ */
+class AssertProductAttributeAbsenceInTemplateGroups extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert that deleted attribute isn't displayed in Product template's Groups section
+     *
+     * @param CatalogAttributeSet $productTemplate
+     * @param CatalogProductSetIndex $productSetIndex
+     * @param CatalogProductSetEdit $productSetEdit
+     * @return void
+     */
+    public function processAssert(
+        CatalogAttributeSet $productTemplate,
+        CatalogProductSetIndex $productSetIndex,
+        CatalogProductSetEdit $productSetEdit
+    ) {
+        $filter = ['set_name' => $productTemplate->getAttributeSetName()];
+        $productSetIndex->open();
+        $productSetIndex->getGrid()->searchAndOpen($filter);
+
+        $attributeCode = $productTemplate
+            ->getDataFieldConfig('assigned_attributes')['source']
+            ->getAttributes()[0]
+            ->getAttributeCode();
+
+        \PHPUnit_Framework_Assert::assertFalse(
+            $productSetEdit->getAttributeSetEditBlock()->checkProductAttribute($attributeCode),
+            "Attribute " . $attributeCode . " is present in Product template's Groups section."
+        );
+    }
+
+    /**
+     * Text absent Product Attribute in Product template's Groups section
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return "Product Attribute is absent in Product template's Groups section.";
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInUnassignedAttributes.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInUnassignedAttributes.php
new file mode 100644
index 0000000000000000000000000000000000000000..e5b6f333d6de4cbd81801e5368adf6b0dcb112ca
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInUnassignedAttributes.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Fixture\CatalogAttributeSet;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex;
+
+/**
+ * Class AssertProductAttributeAbsenceInUnassignedAttributes
+ * Checks that product attribute isn't displayed in Product template's Unassigned Attributes section
+ */
+class AssertProductAttributeAbsenceInUnassignedAttributes extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert that deleted attribute isn't displayed in Product template's Unassigned Attributes section
+     *
+     * @param CatalogAttributeSet $productTemplate
+     * @param CatalogProductSetIndex $productSetIndex
+     * @param CatalogProductSetEdit $productSetEdit
+     * @return void
+     */
+    public function processAssert(
+        CatalogAttributeSet $productTemplate,
+        CatalogProductSetIndex $productSetIndex,
+        CatalogProductSetEdit $productSetEdit
+    ) {
+        $filter = ['set_name' => $productTemplate->getAttributeSetName()];
+        $productSetIndex->open();
+        $productSetIndex->getGrid()->searchAndOpen($filter);
+
+        $attributeCode = $productTemplate
+            ->getDataFieldConfig('assigned_attributes')['source']
+            ->getAttributes()[0]
+            ->getAttributeCode();
+
+        \PHPUnit_Framework_Assert::assertFalse(
+            $productSetEdit->getAttributeSetEditBlock()->checkUnassignedProductAttribute($attributeCode),
+            "Attribute " . $attributeCode . " is present in Unassigned Product template's section."
+        );
+    }
+
+    /**
+     * Text absent Product Attribute Unassigned Product template's section
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return "Product Attribute is absent in Unassigned Product template's section.";
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInVariationsSearch.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInVariationsSearch.php
new file mode 100644
index 0000000000000000000000000000000000000000..c913d8fc6e602a82813a43d91ce7dd433e52dddd
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInVariationsSearch.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Fixture\CatalogProductAttribute;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+
+/**
+ * Class AssertProductAttributeAbsenceInVariationsSearch
+ * Check that deleted attribute can't be added to product template on Product Page via Add Attribute control
+ */
+class AssertProductAttributeAbsenceInVariationsSearch extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert that deleted attribute can't be added to product template on Product Page via Add Attribute control
+     *
+     * @param CatalogProductAttribute $productAttribute
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductNew $newProductPage
+     * @param CatalogProductEdit $productEdit
+     * @return void
+     */
+    public function processAssert
+    (
+        CatalogProductAttribute $productAttribute,
+        CatalogProductIndex $productGrid,
+        CatalogProductEdit $productEdit,
+        CatalogProductNew $newProductPage
+    ) {
+        $productGrid->open();
+        $productGrid->getGridPageActionBlock()->addProduct('simple');
+        $productEdit->getForm()->openVariationsTab();
+        \PHPUnit_Framework_Assert::assertFalse(
+            $newProductPage->getForm()->checkAttributeInVariationsSearchAttributeForm($productAttribute),
+            "Product attribute found in Attribute Search form."
+        );
+    }
+
+    /**
+     * Text absent Product Attribute in Attribute Search form
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return "Product Attribute is absent in Attribute Search form.";
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareBlockOnCmsPage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareBlockOnCmsPage.php
new file mode 100644
index 0000000000000000000000000000000000000000..1ac1b0e824639b5cedece22fea2dd41c1deef35d
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareBlockOnCmsPage.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Client\Browser;
+use Mtf\Fixture\FixtureFactory;
+use Magento\Cms\Test\Page\CmsIndex;
+use Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Class AssertProductCompareBlockOnCmsPage
+ */
+class AssertProductCompareBlockOnCmsPage extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert that Compare Products block is presented on CMS pages.
+     * Block contains information about compared products
+     *
+     * @param array $products
+     * @param CmsIndex $cmsIndex
+     * @param FixtureFactory $fixtureFactory
+     * @param Browser $browser
+     * @return void
+     */
+    public function processAssert(array $products, CmsIndex $cmsIndex, FixtureFactory $fixtureFactory, Browser $browser)
+    {
+        $newCmsPage = $fixtureFactory->createByCode('cmsPage', ['dataSet' => 'with_compare']);
+        $newCmsPage->persist();
+        $browser->open($_ENV['app_frontend_url'] . $newCmsPage->getIdentifier());
+        foreach ($products as &$product) {
+            $product = $product->getName();
+        }
+        \PHPUnit_Framework_Assert::assertEquals(
+            $products,
+            $cmsIndex->getCompareProductsBlock()->getProducts(),
+            'Compare product block contains NOT valid information about compared products.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Compare product block contains valid information about compared products.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareItemsLink.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareItemsLink.php
new file mode 100644
index 0000000000000000000000000000000000000000..0e6900da87a6d2fd35f17741db79b707398aad6b
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareItemsLink.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Cms\Test\Page\CmsIndex;
+
+/**
+ * Class AssertProductCompareItemsLink
+ */
+class AssertProductCompareItemsLink extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert that link "Compare Products..." on top menu of page
+     *
+     * @param array $products
+     * @param CmsIndex $cmsIndex
+     * @return void
+     */
+    public function processAssert(array $products, CmsIndex $cmsIndex)
+    {
+        $productQty = count($products);
+        $qtyOnPage = $cmsIndex->getLinksBlock()->getQtyInCompareList();
+
+        \PHPUnit_Framework_Assert::assertEquals(
+            $productQty,
+            $qtyOnPage,
+            'Qty is not correct in "Compare Products" link.'
+        );
+
+        $compareProductUrl = '/catalog/product_compare/';
+        \PHPUnit_Framework_Assert::assertTrue(
+            strpos($cmsIndex->getLinksBlock()->getLinkUrl('Compare Products'), $compareProductUrl) !== false,
+            'Compare product link isn\'t lead to Compare Product Page.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return '"Compare Products..." link on top menu of page is correct.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareItemsLinkIsAbsent.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareItemsLinkIsAbsent.php
new file mode 100644
index 0000000000000000000000000000000000000000..6cdcee88fe27aacfdd06334b2befbc57e3f50309
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareItemsLinkIsAbsent.php
@@ -0,0 +1,65 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Magento\Cms\Test\Page\CmsIndex;
+use Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Class AssertProductCompareItemsLinkIsAbsent
+ */
+class AssertProductCompareItemsLinkIsAbsent extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert compare products link is NOT visible at the top of page.
+     *
+     * @param CmsIndex $cmsIndex
+     * @return void
+     */
+    public function processAssert(CmsIndex $cmsIndex)
+    {
+        \PHPUnit_Framework_Assert::assertFalse(
+            $cmsIndex->getLinksBlock()->getQtyInCompareList(),
+            'The link "Compare Products..." is visible at the top of page.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'The link is NOT visible at the top of page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductComparePage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductComparePage.php
new file mode 100644
index 0000000000000000000000000000000000000000..d28ecf697f4c48aa94591932e35a44d234315c53
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductComparePage.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Cms\Test\Page\CmsIndex;
+use Magento\Catalog\Test\Page\Product\CatalogProductCompare;
+
+/**
+ * Class AssertProductComparePage
+ * Assert that "Compare Product" page contains product(s) that was added
+ */
+class AssertProductComparePage extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Product attribute on compare product page
+     *
+     * @var array
+     */
+    protected $attributeProduct = [
+        'name',
+        'price',
+        'sku' => 'SKU',
+        'description' => 'Description',
+        'short_description' => 'Short Description'
+    ];
+
+    /**
+     * Assert that "Compare Product" page contains product(s) that was added
+     * - Product name
+     * - Price
+     * - SKU
+     * - Description (if exists, else text "No")
+     * - Short Description (if exists, else text "No")
+     *
+     * @param array $products
+     * @param CatalogProductCompare $comparePage
+     * @param CmsIndex $cmsIndex
+     * @return void
+     *
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     */
+    public function processAssert(
+        array $products,
+        CatalogProductCompare $comparePage,
+        CmsIndex $cmsIndex
+    ) {
+        $cmsIndex->open();
+        $cmsIndex->getLinksBlock()->openLink("Compare Products");
+        foreach ($products as $key => $product) {
+            foreach ($this->attributeProduct as $attributeKey => $attribute) {
+                $value = $attribute;
+                $attribute = is_numeric($attributeKey) ? $attribute : $attributeKey;
+
+                $attributeValue = $attribute != 'price'
+                    ? ($product->hasData($attribute)
+                        ? $product->getData($attribute)
+                        : 'N/A')
+                    : ($product->getDataFieldConfig('price')['source']->getPreset() !== null
+                        ? $product->getDataFieldConfig('price')['source']->getPreset()['compare_price']
+                        : number_format($product->getPrice(), 2));
+
+                $attribute = is_numeric($attributeKey) ? 'info' : 'attribute';
+                \PHPUnit_Framework_Assert::assertEquals(
+                    $attributeValue,
+                    $comparePage->getCompareProductsBlock()->{'getProduct' . ucfirst($attribute)}($key + 1, $value),
+                    'Product "' . $product->getName() . '" is\'n equals with data from fixture.'
+                );
+            }
+        }
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return '"Compare Product" page has valid data for all products.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareRemoveLastProductMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareRemoveLastProductMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..456c2075f8807fa6f5ae80c7d9bbd3216edbc89e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareRemoveLastProductMessage.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Page\Product\CatalogProductCompare;
+
+/**
+ * Class AssertProductCompareRemoveLastProductMessage
+ * Assert message on "Compare Products" page after removing product
+ */
+class AssertProductCompareRemoveLastProductMessage extends AbstractConstraint
+{
+    const SUCCESS_MESSAGE = 'You have no items to compare.';
+
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * After removing last product message is appeared on "Compare Products" page
+     *
+     * @param CatalogProductCompare $comparePage
+     * @return void
+     */
+    public function processAssert(CatalogProductCompare $comparePage)
+    {
+        $comparePage->open();
+        $actualMessage = $comparePage->getCompareProductsBlock()->getEmptyMessage();
+        \PHPUnit_Framework_Assert::assertEquals(
+            self::SUCCESS_MESSAGE,
+            $actualMessage,
+            'Wrong success message is displayed.'
+            . "\nExpected: " . self::SUCCESS_MESSAGE
+            . "\nActual: " . $actualMessage
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'After removing last product the message appears on "Compare Products" page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertGroupedPriceOnProductPage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessAddMessage.php
similarity index 59%
rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertGroupedPriceOnProductPage.php
rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessAddMessage.php
index 0e364e2975f53b7a04153550b4974f2afbf98207..ec8e9aaa84bf82f9ae85455e3f2442a8c1dca437 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertGroupedPriceOnProductPage.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessAddMessage.php
@@ -24,24 +24,26 @@
 
 namespace Magento\Catalog\Test\Constraint;
 
-use Mtf\Fixture\FixtureInterface;
 use Mtf\Constraint\AbstractConstraint;
 use Magento\Catalog\Test\Page\Product\CatalogProductView;
+use Mtf\Fixture\FixtureInterface;
 
 /**
- * Class AssertGroupedPriceOnProductPage
+ * Class AssertProductCompareSuccessAddMessage
  */
-class AssertGroupedPriceOnProductPage extends AbstractConstraint
+class AssertProductCompareSuccessAddMessage extends AbstractConstraint
 {
+    const SUCCESS_MESSAGE = 'You added product %s to the comparison list.';
+
     /**
      * Constraint severeness
      *
      * @var string
      */
-    protected $severeness = 'low';
+    protected $severeness = 'high';
 
     /**
-     * Assert that displayed grouped price on product page equals passed from fixture
+     * Assert success message is presented on page
      *
      * @param CatalogProductView $catalogProductView
      * @param FixtureInterface $product
@@ -49,22 +51,15 @@ class AssertGroupedPriceOnProductPage extends AbstractConstraint
      */
     public function processAssert(CatalogProductView $catalogProductView, FixtureInterface $product)
     {
-        $catalogProductView->init($product);
-        $catalogProductView->open();
-        $fields = $product->getData();
-        $groupPrice = $catalogProductView->getViewBlock()->getProductPrice();
-        $groupPrice = isset($groupPrice['price_special_price'])
-            ? $groupPrice['price_special_price']
-            : null;
-        if (isset($fields['group_price'])) {
-            foreach ($fields['group_price'] as $itemGroupPrice) {
-                \PHPUnit_Framework_Assert::assertEquals(
-                    $itemGroupPrice['price'],
-                    $groupPrice,
-                    'Assert that displayed grouped price on product page NOT equals passed from fixture.'
-                );
-            }
-        }
+        $successMessage = sprintf(self::SUCCESS_MESSAGE, $product->getName());
+        $actualMessage = $catalogProductView->getMessagesBlock()->getSuccessMessages();
+        \PHPUnit_Framework_Assert::assertEquals(
+            $successMessage,
+            $actualMessage,
+            'Wrong success message is displayed.'
+            . "\nExpected: " . $successMessage
+            . "\nActual: " . $actualMessage
+        );
     }
 
     /**
@@ -74,6 +69,6 @@ class AssertGroupedPriceOnProductPage extends AbstractConstraint
      */
     public function toString()
     {
-        return 'Assert that displayed grouped price on product page equals passed from fixture.';
+        return 'Product has been added compare products list.';
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessRemoveAllProductsMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessRemoveAllProductsMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..a4ce76d407b1e3c7312dd8f19e07a6fd90583d45
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessRemoveAllProductsMessage.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Page\Product\CatalogProductView;
+
+/**
+ * Class AssertProductCompareSuccessRemoveAllProductsMessage
+ */
+class AssertProductCompareSuccessRemoveAllProductsMessage extends AbstractConstraint
+{
+    const SUCCESS_MESSAGE = 'You cleared the comparison list.';
+
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'high';
+
+    /**
+     * Assert message is appeared on "Compare Products" page.
+     *
+     * @param CatalogProductView $catalogProductView
+     * @return void
+     */
+    public function processAssert(CatalogProductView $catalogProductView)
+    {
+        $actualMessage = $catalogProductView->getMessagesBlock()->getSuccessMessages();
+        \PHPUnit_Framework_Assert::assertEquals(
+            self::SUCCESS_MESSAGE,
+            $actualMessage,
+            'Wrong success message is displayed.'
+            . "\nExpected: " . self::SUCCESS_MESSAGE
+            . "\nActual: " . $actualMessage
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Compare Product success message is present.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessRemoveMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessRemoveMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..2a210d9958e1cf5259ed8f8a30c1b6956b44b2a0
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessRemoveMessage.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Fixture\FixtureInterface;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Page\Product\CatalogProductCompare;
+
+/**
+ * Class AssertProductCompareSuccessRemoveMessage
+ * Assert message is appeared on "Compare Products" block on myAccount page
+ */
+class AssertProductCompareSuccessRemoveMessage extends AbstractConstraint
+{
+    const SUCCESS_MESSAGE = 'You removed product %s from the comparison list.';
+
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert message is appeared on "Compare Products" block on myAccount page
+     *
+     * @param CatalogProductCompare $catalogProductCompare
+     * @param FixtureInterface $product
+     * @return void
+     */
+    public function processAssert(CatalogProductCompare $catalogProductCompare, FixtureInterface $product)
+    {
+        $successMessage = sprintf(self::SUCCESS_MESSAGE, $product->getName());
+        $actualMessage = $catalogProductCompare->getMessagesBlock()->getSuccessMessages();
+        \PHPUnit_Framework_Assert::assertEquals($successMessage, $actualMessage, 'Wrong success message is displayed.');
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Product has been removed from compare products list.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCustomOptionsOnProductPage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCustomOptionsOnProductPage.php
new file mode 100755
index 0000000000000000000000000000000000000000..2de9af98ded0acac2c3514680a3c1ea25cdad8f3
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCustomOptionsOnProductPage.php
@@ -0,0 +1,158 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Constraint\AbstractAssertForm;
+use Mtf\Fixture\FixtureInterface;
+use Magento\Catalog\Test\Page\Product\CatalogProductView;
+use Magento\Catalog\Test\Fixture\CatalogProductSimple;
+
+/**
+ * Class AssertProductCustomOptionsOnProductPage
+ */
+class AssertProductCustomOptionsOnProductPage extends AbstractAssertForm
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Skipped field for custom options
+     *
+     * @var array
+     */
+    protected $skippedFieldOptions = [
+        'Field' => [
+            'price_type',
+            'sku',
+        ],
+        'Area' => [
+            'price_type',
+            'sku',
+        ],
+        'Drop-down' => [
+            'price_type',
+            'sku',
+        ],
+        'File' => [
+            'price_type',
+            'sku',
+        ],
+        'Radio Buttons' => [
+            'price_type',
+            'sku',
+        ],
+        'Checkbox' => [
+            'price_type',
+            'sku',
+        ],
+        'Multiple Select' => [
+            'price_type',
+            'sku',
+        ],
+        'Date' => [
+            'price_type',
+            'sku',
+        ],
+        'Date & Time' => [
+            'price_type',
+            'sku',
+        ],
+        'Time' => [
+            'price_type',
+            'sku',
+        ]
+    ];
+
+    /**
+     * Assertion that commodity options are displayed correctly
+     *
+     * @param CatalogProductView $catalogProductView
+     * @param FixtureInterface $product
+     * @return void
+     */
+    public function processAssert(CatalogProductView $catalogProductView, FixtureInterface $product)
+    {
+        // TODO fix initialization url for frontend page
+        // Open product view page
+        $catalogProductView->init($product);
+        $catalogProductView->open();
+        // Prepare data
+        $formCustomOptions = $catalogProductView->getCustomOptionsBlock()->getOptions($product);
+        $prices = $catalogProductView->getViewBlock()->getProductPriceBlock()->getPrice();
+        $actualPrice = isset($prices['price_special_price'])
+            ? $prices['price_special_price']
+            : $prices['price_regular_price'];
+        $fixtureCustomOptions = $this->prepareOptions($product, $actualPrice);
+        $error = $this->verifyData($fixtureCustomOptions, $formCustomOptions);
+        \PHPUnit_Framework_Assert::assertEmpty($error, $error);
+    }
+
+    /**
+     * Preparation options before comparing
+     *
+     * @param FixtureInterface $product
+     * @param int|null $actualPrice
+     * @return array
+     */
+    protected function prepareOptions(FixtureInterface $product, $actualPrice = null)
+    {
+        $customOptions = $product->getCustomOptions();
+        $result = [];
+
+        $actualPrice = $actualPrice ? $actualPrice : $product->getPrice();
+        foreach ($customOptions as $customOption) {
+            $skippedField = isset($this->skippedFieldOptions[$customOption['type']])
+                ? $this->skippedFieldOptions[$customOption['type']]
+                : [];
+            foreach ($customOption['options'] as &$option) {
+                // recalculate percent price
+                if ('Percent' == $option['price_type']) {
+                    $option['price'] = ($actualPrice * $option['price']) / 100;
+                    $option['price'] = round($option['price'], 2);
+                }
+
+                $option = array_diff_key($option, array_flip($skippedField));
+            }
+
+            $result[$customOption['title']] = $customOption;
+        }
+
+        return $result;
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Value of custom option on the page is correct.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicateForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicateForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..2fde4a0da852f217a420b93b919445f86b5151b8
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicateForm.php
@@ -0,0 +1,140 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Fixture\FixtureInterface;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+
+/**
+ * Class AssertProductDuplicateForm
+ */
+class AssertProductDuplicateForm extends AssertProductForm
+{
+    /**
+     * Formatting options for numeric values
+     *
+     * @var array
+     */
+    protected $formattingOptions = [
+        'price' => [
+            'decimals' => 2,
+            'dec_point' => '.',
+            'thousands_sep' => ''
+        ],
+        'qty' => [
+            'decimals' => 4,
+            'dec_point' => '.',
+            'thousands_sep' => ''
+        ],
+        'weight' => [
+            'decimals' => 4,
+            'dec_point' => '.',
+            'thousands_sep' => ''
+        ]
+    ];
+
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert form data equals fixture data
+     *
+     * @param FixtureInterface $product
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductEdit $productPage
+     * @return void
+     */
+    public function processAssert(
+        FixtureInterface $product,
+        CatalogProductIndex $productGrid,
+        CatalogProductEdit $productPage
+    ) {
+        $filter = ['sku' => $product->getSku() . '-1'];
+        $productGrid->open()->getProductGrid()->searchAndOpen($filter);
+
+        $formData = $productPage->getForm()->getData($product);
+        $fixtureData = $this->prepareFixtureData($product->getData());
+
+        $errors = $this->verifyData($fixtureData, $formData);
+        \PHPUnit_Framework_Assert::assertEmpty($errors, $errors);
+    }
+
+    /**
+     * Prepares fixture data for comparison
+     *
+     * @param array $data
+     * @param array $sortFields [optional]
+     * @return array
+     */
+    protected function prepareFixtureData(array $data, array $sortFields = [])
+    {
+        $compareData = array_filter($data);
+
+        array_walk_recursive(
+            $compareData,
+            function (&$item, $key, $formattingOptions) {
+                if (isset($formattingOptions[$key])) {
+                    $item = number_format(
+                        $item,
+                        $formattingOptions[$key]['decimals'],
+                        $formattingOptions[$key]['dec_point'],
+                        $formattingOptions[$key]['thousands_sep']
+                    );
+                }
+            },
+            $this->formattingOptions
+        );
+
+        if (isset($compareData['status'])) {
+            $compareData['status'] = 'Product offline';
+        }
+        if (isset($compareData['quantity_and_stock_status']['qty'])) {
+            $compareData['quantity_and_stock_status']['qty'] = '';
+        }
+        if (isset($compareData['special_price'])) {
+            $compareData['special_price'] = ['special_price' => $compareData['special_price']];
+        }
+        $compareData['sku'] .= '-1';
+        $compareData['quantity_and_stock_status']['is_in_stock'] = 'Out of Stock';
+        unset($compareData['category_ids'], $compareData['id']);
+
+        return $compareData;
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Form data equals to fixture data of duplicated product.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicateIsNotDisplayingOnFrontend.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicateIsNotDisplayingOnFrontend.php
new file mode 100644
index 0000000000000000000000000000000000000000..35b0008b4909d062230b0077e974d3eb6bc8304a
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicateIsNotDisplayingOnFrontend.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Class AssertProductDuplicateIsNotDisplayingOnFrontend
+ */
+class AssertProductDuplicateIsNotDisplayingOnFrontend extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'high';
+
+    /**
+     * Assert that product duplicate is not displayed on front-end
+     *
+     * @return void
+     */
+    public function processAssert()
+    {
+        // TODO mage to MAGETWO-25523
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'The product does not appear on the frontend.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicateMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicateMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..b01a1731bbf21dc3d84df9d86b60cbce8579ed2d
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicateMessage.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+
+/**
+ * Class AssertProductDuplicateMessage
+ */
+class AssertProductDuplicateMessage extends AbstractConstraint
+{
+    /**
+     * Text value to be checked
+     */
+    const DUPLICATE_MESSAGE = 'You duplicated the product.';
+
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'high';
+
+    /**
+     * Checking the output message successful product duplication
+     *
+     * @param CatalogProductEdit $productPage
+     * @return void
+     */
+    public function processAssert(CatalogProductEdit $productPage)
+    {
+        $actualMessages = $productPage->getMessagesBlock()->getSuccessMessages();
+        $actualMessages = is_array($actualMessages) ? $actualMessages : [$actualMessages];
+        \PHPUnit_Framework_Assert::assertContains(
+            self::DUPLICATE_MESSAGE,
+            $actualMessages,
+            'Wrong duplicated message is displayed.'
+            . "\nExpected: " . self::DUPLICATE_MESSAGE
+            . "\nActual:\n" . implode("\n - ", $actualMessages)
+        );
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Product duplicated message is present.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicatedInGrid.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicatedInGrid.php
new file mode 100644
index 0000000000000000000000000000000000000000..c3de80ebfb82cfe5a9cd085479fe99b530188c74
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicatedInGrid.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Fixture\FixtureInterface;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+
+/**
+ * Class AssertProductDuplicatedInGrid
+ */
+class AssertProductDuplicatedInGrid extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert that duplicated product is found by sku and has correct product type, product template,
+     * product status disabled and out of stock
+     *
+     * @param FixtureInterface $product
+     * @param CatalogProductIndex $productGrid
+     * @return void
+     */
+    public function processAssert(FixtureInterface $product, CatalogProductIndex $productGrid)
+    {
+        $config = $product->getDataConfig();
+        $filter = [
+            'name' => $product->getName(),
+            'visibility' => $product->getVisibility(),
+            'status' => 'Disabled',
+            'sku' => $product->getSku() . '-1',
+            'type' => ucfirst($config['create_url_params']['type']) . ' Product',
+            'price_to' => number_format($product->getPrice(), 2)
+        ];
+
+        $productGrid->open()
+            ->getProductGrid()
+            ->search($filter);
+
+        $filter['price_to'] = '$' . $filter['price_to'];
+        \PHPUnit_Framework_Assert::assertTrue(
+            $productGrid->getProductGrid()->isRowVisible($filter, false),
+            'Product duplicate is absent in Products grid.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'The product has been successfully found, according to the filters.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductForm.php
old mode 100644
new mode 100755
index 267cfb97e52b725fafda50c94c09edb75632b554..b5ade64e7f27a5c7e485181a237e26a10a99df1f
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductForm.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductForm.php
@@ -24,38 +24,22 @@
 
 namespace Magento\Catalog\Test\Constraint;
 
+use Mtf\Constraint\AbstractAssertForm;
 use Mtf\Fixture\FixtureInterface;
-use Mtf\Constraint\AbstractConstraint;
-use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
 use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
 
 /**
  * Class AssertProductForm
  */
-class AssertProductForm extends AbstractConstraint
+class AssertProductForm extends AbstractAssertForm
 {
     /**
-     * Formatting options for numeric values
+     * Sort fields for fixture and form data
      *
      * @var array
      */
-    protected $formattingOptions = [
-        'price' => [
-            'decimals' => 2,
-            'dec_point' => '.',
-            'thousands_sep' => ''
-        ],
-        'qty' => [
-            'decimals' => 4,
-            'dec_point' => '.',
-            'thousands_sep' => ''
-        ],
-        'weight' => [
-            'decimals' => 4,
-            'dec_point' => '.',
-            'thousands_sep' => ''
-        ]
-    ];
+    protected $sortFields = [];
 
     /**
      * Constraint severeness
@@ -78,86 +62,47 @@ class AssertProductForm extends AbstractConstraint
         CatalogProductEdit $productPage
     ) {
         $filter = ['sku' => $product->getSku()];
-        $productGrid->open()->getProductGrid()->searchAndOpen($filter);
-
-        $formData = $productPage->getForm()->getData($product);
-        $fixtureData = $this->prepareFixtureData($product);
+        $productGrid->open();
+        $productGrid->getProductGrid()->searchAndOpen($filter);
 
-        $errors = $this->compareArray($fixtureData, $formData);
-        \PHPUnit_Framework_Assert::assertTrue(
-            empty($errors),
-            "These data must be equal to each other:\n" . implode("\n", $errors)
-        );
+        $fixtureData = $this->prepareFixtureData($product->getData(), $this->sortFields);
+        $formData = $this->prepareFormData($productPage->getForm()->getData($product), $this->sortFields);
+        $error = $this->verifyData($fixtureData, $formData);
+        \PHPUnit_Framework_Assert::assertTrue(empty($error), $error);
     }
 
     /**
-     * Prepares and returns data to the fixture, ready for comparison
+     * Prepares fixture data for comparison
      *
-     * @param FixtureInterface $product
+     * @param array $data
+     * @param array $sortFields [optional]
      * @return array
      */
-    protected function prepareFixtureData(FixtureInterface $product)
+    protected function prepareFixtureData(array $data, array $sortFields = [])
     {
-        $compareData = $product->getData();
-        $compareData = array_filter($compareData);
-
-        array_walk_recursive(
-            $compareData,
-            function (&$item, $key, $formattingOptions) {
-                if (isset($formattingOptions[$key])) {
-                    $item = number_format(
-                        $item,
-                        $formattingOptions[$key]['decimals'],
-                        $formattingOptions[$key]['dec_point'],
-                        $formattingOptions[$key]['thousands_sep']
-                    );
-                }
-            },
-            $this->formattingOptions
-        );
-
-        if (isset($compareData['special_price'])) {
-            $compareData['special_price'] = ['special_price' => $compareData['special_price']];
+        if (isset($data['website_ids']) && !is_array($data['website_ids'])) {
+            $data['website_ids'] = [$data['website_ids']];
         }
 
-        return $compareData;
+        foreach ($sortFields as $path) {
+            $data = $this->sortDataByPath($data, $path);
+        }
+        return $data;
     }
 
     /**
-     * Comparison of multidimensional arrays
+     * Prepares form data for comparison
      *
-     * @param array $fixtureData
-     * @param array $formData
+     * @param array $data
+     * @param array $sortFields [optional]
      * @return array
-     *
-     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      */
-    protected function compareArray(array $fixtureData, array $formData)
+    protected function prepareFormData(array $data, array $sortFields = [])
     {
-        $errors = [];
-        $keysDiff = array_diff(array_keys($formData), array_keys($fixtureData));
-        if (!empty($keysDiff)) {
-            return ['- fixture data do not correspond to form data in composition.'];
+        foreach ($sortFields as $path) {
+            $data = $this->sortDataByPath($data, $path);
         }
-
-        foreach ($fixtureData as $key => $value) {
-            if (is_array($value) && is_array($formData[$key])
-                && ($innerErrors = $this->compareArray($value, $formData[$key])) && !empty($innerErrors)
-            ) {
-                $errors = array_merge($errors, $innerErrors);
-            } elseif ($value != $formData[$key]) {
-                $fixtureValue = empty($value) ? '<empty-value>' : $value;
-                $formValue = empty($formData[$key]) ? '<empty-value>' : $formData[$key];
-                $errors = array_merge(
-                    $errors,
-                    [
-                        "error key -> '{$key}' : error value ->  '{$fixtureValue}' does not equal -> '{$formValue}'"
-                    ]
-                );
-            }
-        }
-
-        return $errors;
+        return $data;
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductGroupedPriceOnProductPage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductGroupedPriceOnProductPage.php
new file mode 100644
index 0000000000000000000000000000000000000000..05902a4b452a47c38a696f6441bec7df632a57a7
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductGroupedPriceOnProductPage.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Fixture\FixtureInterface;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Block\Product\View;
+use Magento\Catalog\Test\Page\Product\CatalogProductView;
+
+/**
+ * Class AssertProductGroupedPriceOnProductPage
+ */
+class AssertProductGroupedPriceOnProductPage extends AbstractConstraint implements AssertPriceOnProductPageInterface
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Error message
+     *
+     * @var string
+     */
+    protected $errorMessage = 'That displayed grouped price on product page is NOT equal to one, passed from fixture.';
+
+    /**
+     * Customer group
+     *
+     * @var string
+     */
+    protected $customerGroup;
+
+    /**
+     * Assert that displayed grouped price on product page equals passed from fixture
+     *
+     * @param CatalogProductView $catalogProductView
+     * @param FixtureInterface $product
+     * @return void
+     */
+    public function processAssert(CatalogProductView $catalogProductView, FixtureInterface $product)
+    {
+        $catalogProductView->init($product);
+        $catalogProductView->open();
+
+        //Process assertions
+        $this->assertPrice($product, $catalogProductView);
+    }
+
+    /**
+     * Set $errorMessage for grouped price assert
+     *
+     * @param string $errorMessage
+     * @return void
+     */
+    public function setErrorMessage($errorMessage)
+    {
+        $this->errorMessage = $errorMessage;
+    }
+
+    /**
+     * Verify product special price on product view page
+     *
+     * @param FixtureInterface $product
+     * @param CatalogProductView $catalogProductView
+     * @param string $block [optional]
+     * @param string $customerGroup [optional]
+     * @return void
+     */
+    public function assertPrice(
+        FixtureInterface $product,
+        CatalogProductView $catalogProductView,
+        $block = '',
+        $customerGroup = 'NOT LOGGED IN'
+    ) {
+        $this->customerGroup = $customerGroup;
+        $groupPrice = $this->getGroupedPrice($catalogProductView->{'get' . $block . 'ViewBlock'}(), $product);
+        \PHPUnit_Framework_Assert::assertEquals($groupPrice['fixture'], $groupPrice['onPage'], $this->errorMessage);
+    }
+
+    /**
+     * Get grouped price with fixture product and product page
+     *
+     * @param View $view
+     * @param FixtureInterface $product
+     * @return array
+     */
+    protected function getGroupedPrice(View $view, FixtureInterface $product)
+    {
+        $fields = $product->getData();
+        $groupPrice['onPage'] = $view->getProductPrice();
+        $groupPrice['onPage'] = isset($groupPrice['onPage']['price_special_price'])
+            ? $groupPrice['onPage']['price_special_price']
+            : null;
+        $groupPrice['fixture'] = number_format(
+            $fields['group_price'][array_search($this->customerGroup, $fields['group_price'])]['price'],
+            2
+        );
+
+        return $groupPrice;
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Assert that displayed grouped price on product page equals passed from fixture.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCart.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCart.php
old mode 100644
new mode 100755
index 83987d7abd5524e702d421c7268a945bab99f450..7b03df6af3cec7f4cab312b8d3353aa4cc2f121d
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCart.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCart.php
@@ -62,7 +62,7 @@ class AssertProductInCart extends AbstractConstraint
             $customOption = $catalogProductView->getCustomOptionsBlock();
             $options = $customOption->getOptions();
             $key = $productOptions[0]['title'];
-            $customOption->selectProductCustomOption(reset($options[$key]['value']));
+            $customOption->selectProductCustomOption($options[$key]['title']);
         }
         $catalogProductView->getViewBlock()->clickAddToCart();
 
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCategory.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCategory.php
index 164eafe6024a2d1312495248c763cdf63427d8e2..4490968398655e8019f8c8634cb5aca2ba87bab8 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCategory.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCategory.php
@@ -58,8 +58,13 @@ class AssertProductInCategory extends AbstractConstraint
         CatalogCategory $category
     ) {
         // Open category view page and check visible product
+        $categoryName = $category->getName();
+        if ($product->hasData('category_ids')) {
+            $categoryIds = $product->getCategoryIds();
+            $categoryName = is_array($categoryIds) ? reset($categoryIds) : $categoryName;
+        }
         $cmsIndex->open();
-        $cmsIndex->getTopmenu()->selectCategoryByName($category->getName());
+        $cmsIndex->getTopmenu()->selectCategoryByName($categoryName);
 
         $isProductVisible = $catalogCategoryView->getListProductBlock()->isProductVisible($product->getName());
         while (!$isProductVisible && $catalogCategoryView->getToolbar()->nextPage()) {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInStock.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInStock.php
old mode 100644
new mode 100755
index 88af87b1409a5472d81a1832f7330bb4ff731029..134d826fd58bd854895b0e1d794bd54cd467ee97
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInStock.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInStock.php
@@ -43,7 +43,7 @@ class AssertProductInStock extends AbstractConstraint
     /**
      * Text value for checking Stock Availability
      */
-    const STOCK_AVAILABILITY = 'In stock';
+    const STOCK_AVAILABILITY = 'in stock';
 
     /**
      * Assert that In Stock status is displayed on product page
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductIsNotDisplayingOnFrontend.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductIsNotDisplayingOnFrontend.php
old mode 100644
new mode 100755
index 97378c339816e27f7aa5323c131c79e1576f414e..399df64eae5297f7fe1792fe99138c1ef1bd18b2
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductIsNotDisplayingOnFrontend.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductIsNotDisplayingOnFrontend.php
@@ -92,7 +92,7 @@ class AssertProductIsNotDisplayingOnFrontend extends AbstractConstraint
      * @param CatalogCategoryView $catalogCategoryView
      * @param CmsIndex $cmsIndex
      * @param FixtureInterface|FixtureInterface[] $product
-     * @param CatalogCategory $category
+     * @param CatalogCategory|null $category
      */
     public function processAssert(
         CatalogProductView $catalogProductView,
@@ -100,7 +100,7 @@ class AssertProductIsNotDisplayingOnFrontend extends AbstractConstraint
         CatalogCategoryView $catalogCategoryView,
         CmsIndex $cmsIndex,
         $product,
-        CatalogCategory $category
+        CatalogCategory $category = null
     ) {
         $this->catalogProductView = $catalogProductView;
         $this->catalogSearchResult = $catalogSearchResult;
@@ -112,8 +112,8 @@ class AssertProductIsNotDisplayingOnFrontend extends AbstractConstraint
         foreach ($products as $product) {
             $errors = array_merge($errors, $this->isNotDisplayingOnFrontendAssert($product));
         }
-        \PHPUnit_Framework_Assert::assertTrue(
-            empty($errors),
+        \PHPUnit_Framework_Assert::assertEmpty(
+            $errors,
             "In the process of checking product availability on the frontend, found the following errors:\n"
             . implode("\n", $errors)
         );
@@ -147,7 +147,7 @@ class AssertProductIsNotDisplayingOnFrontend extends AbstractConstraint
         }
 
         $categoryName = ($product->hasData('category_ids'))
-            ? $product->getCategoryIds()[0]['name']
+            ? $product->getCategoryIds()[0]
             : $this->category->getName();
         $this->cmsIndex->open();
         $this->cmsIndex->getTopmenu()->selectCategoryByName($categoryName);
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductIsNotVisibleInCompareBlock.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductIsNotVisibleInCompareBlock.php
new file mode 100644
index 0000000000000000000000000000000000000000..b158dc7eb74ad116c1c8a15b0bec12c764ec4daf
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductIsNotVisibleInCompareBlock.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Fixture\FixtureInterface;
+use Magento\Cms\Test\Page\CmsIndex;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Customer\Test\Page\CustomerAccountIndex;
+
+/**
+ * Class AssertProductIsNotVisibleInCompareBlock
+ * Assert the product is not displayed on Compare Products block on my account page
+ */
+class AssertProductIsNotVisibleInCompareBlock extends AbstractConstraint
+{
+    const SUCCESS_MESSAGE = 'You have no items to compare.';
+
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert the product is not displayed on Compare Products block on my account page
+     *
+     * @param CmsIndex $cmsIndex
+     * @param CustomerAccountIndex $customerAccountIndex
+     * @param int $countProducts [optional]
+     * @param FixtureInterface $product [optional]
+     * @return void
+     */
+    public function processAssert(
+        CmsIndex $cmsIndex,
+        CustomerAccountIndex $customerAccountIndex,
+        $countProducts = 0,
+        FixtureInterface $product = null
+    ) {
+        $cmsIndex->open();
+        $cmsIndex->getLinksBlock()->openLink("My Account");
+        $compareBlock = $customerAccountIndex->getCompareProductsBlock();
+
+        if (($countProducts > 1) && ($product !== null)) {
+            \PHPUnit_Framework_Assert::assertFalse(
+                $compareBlock->isProductVisibleInCompareBlock($product->getName()),
+                'The product displays on Compare Products block on my account page.'
+            );
+        } else {
+            \PHPUnit_Framework_Assert::assertEquals(
+                self::SUCCESS_MESSAGE,
+                $compareBlock->getEmptyMessage(),
+                'The product displays on Compare Products block on my account page.'
+            );
+        }
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'The message appears on Compare Products block on my account page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductIsNotVisibleInComparePage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductIsNotVisibleInComparePage.php
new file mode 100644
index 0000000000000000000000000000000000000000..922188213d892c181fdf41e73324dc75e0609b18
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductIsNotVisibleInComparePage.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Fixture\FixtureInterface;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Page\Product\CatalogProductCompare;
+
+/**
+ * Class AssertProductIsNotVisibleInComparePage
+ * Assert the product is not displayed on Compare Products page
+ */
+class AssertProductIsNotVisibleInComparePage extends AbstractConstraint
+{
+    const SUCCESS_MESSAGE = 'You have no items to compare.';
+
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert the product is not displayed on Compare Products page
+     *
+     * @param CatalogProductCompare $comparePage
+     * @param FixtureInterface $product
+     * @param int $countProducts [optional]
+     * @return void
+     */
+    public function processAssert(CatalogProductCompare $comparePage, FixtureInterface $product, $countProducts = 0)
+    {
+        $comparePage->open();
+        $compareBlock = $comparePage->getCompareProductsBlock();
+
+        if ($countProducts > 1) {
+            \PHPUnit_Framework_Assert::assertFalse(
+                $compareBlock->isProductVisibleInCompareBlock($product->getName()),
+                'The product displays on Compare Products page.'
+            );
+        } else {
+            \PHPUnit_Framework_Assert::assertEquals(
+                self::SUCCESS_MESSAGE,
+                $compareBlock->getEmptyMessage(),
+                'The product displays on Compare Products page.'
+            );
+        }
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Products is not displayed on Compare Products page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductNotInGrid.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductNotInGrid.php
index a1811ddfa2231a4204db69b231e988e252187612..ad5dcd417cdbf0c9514d6e754f687dbadba11b97 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductNotInGrid.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductNotInGrid.php
@@ -30,6 +30,7 @@ use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
 
 /**
  * Class AssertProductNotInGrid
+ * Assert that Product absence on grid
  */
 class AssertProductNotInGrid extends AbstractConstraint
 {
@@ -41,7 +42,7 @@ class AssertProductNotInGrid extends AbstractConstraint
     protected $severeness = 'low';
 
     /**
-     * Assert that product cannot be found by name and sku.
+     * Assert that product cannot be found by name and sku
      *
      * @param FixtureInterface|FixtureInterface[] $product
      * @param CatalogProductIndex $productGrid
@@ -61,7 +62,7 @@ class AssertProductNotInGrid extends AbstractConstraint
     }
 
     /**
-     * Returns a string representation of the object.
+     * Returns a string representation of the object
      *
      * @return string
      */
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductNotSearchableBySku.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductNotSearchableBySku.php
new file mode 100644
index 0000000000000000000000000000000000000000..4a97fa372299cc8548bc23579079d5d732459404
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductNotSearchableBySku.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Fixture\FixtureInterface;
+use Magento\Cms\Test\Page\CmsIndex;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\CatalogSearch\Test\Page\CatalogsearchResult;
+
+/**
+ * Class AssertProductNotSearchableBySku
+ * Assert that product cannot be found via Quick Search using searchable product attributes.
+ */
+class AssertProductNotSearchableBySku extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert that product cannot be found via Quick Search using searchable product attributes.
+     *
+     * @param CatalogsearchResult $catalogSearchResult
+     * @param CmsIndex $cmsIndex
+     * @param FixtureInterface $product
+     * @return void
+     */
+    public function processAssert(
+        CatalogsearchResult $catalogSearchResult,
+        CmsIndex $cmsIndex,
+        FixtureInterface $product
+    ) {
+        $cmsIndex->open();
+        $cmsIndex->getSearchBlock()->search($product->getSku());
+        \PHPUnit_Framework_Assert::assertFalse(
+            $catalogSearchResult->getListProductBlock()->isProductVisible($product->getName()),
+            'Product was found by SKU.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return "Product is not searchable by SKU.";
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductNotVisibleInCategory.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductNotVisibleInCategory.php
new file mode 100755
index 0000000000000000000000000000000000000000..e8a88c5ae6b75e55f0bbef75c60bf5781f5e3e2f
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductNotVisibleInCategory.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Fixture\FixtureInterface;
+use Magento\Cms\Test\Page\CmsIndex;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Fixture\CatalogCategory;
+use Magento\Catalog\Test\Page\Category\CatalogCategoryView;
+
+/**
+ * Class AssertProductNotVisibleInCategory
+ */
+class AssertProductNotVisibleInCategory extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert that product is not visible in the assigned category
+     *
+     * @param CatalogCategoryView $catalogCategoryView
+     * @param CmsIndex $cmsIndex
+     * @param FixtureInterface $product
+     * @param CatalogCategory|null $category
+     * @return void
+     */
+    public function processAssert(
+        CatalogCategoryView $catalogCategoryView,
+        CmsIndex $cmsIndex,
+        FixtureInterface $product,
+        CatalogCategory $category = null
+    ) {
+        $categoryName = $category
+            ? $category->getName()
+            : $product->getCategoryIds()[0];
+        $cmsIndex->open();
+        $cmsIndex->getTopmenu()->selectCategoryByName($categoryName);
+
+        $isProductVisible = $catalogCategoryView->getListProductBlock()->isProductVisible($product->getName());
+        while (!$isProductVisible && $catalogCategoryView->getToolbar()->nextPage()) {
+            $isProductVisible = $catalogCategoryView->getListProductBlock()->isProductVisible($product->getName());
+        }
+        \PHPUnit_Framework_Assert::assertFalse(
+            $isProductVisible,
+            'Product is exist on category page.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Product is absent in the assigned category.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductOutOfStock.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductOutOfStock.php
old mode 100644
new mode 100755
index 7d340ceddbce8c86d3c1660b1a1da49da816235c..c4e35745f3ea5ef93a9033de17e1a88a431b8417
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductOutOfStock.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductOutOfStock.php
@@ -43,7 +43,7 @@ class AssertProductOutOfStock extends AbstractConstraint
     /**
      * Text value for checking Stock Availability
      */
-    const STOCK_AVAILABILITY = 'Out of stock';
+    const STOCK_AVAILABILITY = 'out of stock';
 
     /**
      * Assert that Out of Stock status is displayed on product page
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductPage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductPage.php
old mode 100644
new mode 100755
index 52f18eade7d156322bfce35e6c581ffa7288c7b7..3dd53067ba8fbd91f77502bb726160d3e284bd6d
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductPage.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductPage.php
@@ -47,6 +47,19 @@ class AssertProductPage extends AbstractConstraint
      */
     protected $severeness = 'low';
 
+    /**
+     * Error messages
+     *
+     * @var array
+     */
+    protected $errorsMessages = [
+        'name' => '- product name on product view page is not correct.',
+        'sku' => '- product sku on product view page is not correct.',
+        'regular_price' => '- product regular price on product view page is not correct.',
+        'short_description' => '- product short description on product view page is not correct.',
+        'description' => '- product description on product view page is not correct.'
+    ];
+
     /**
      * Assertion that the product page is displayed correctly
      *
@@ -62,70 +75,79 @@ class AssertProductPage extends AbstractConstraint
         $catalogProductView->init($product);
         $catalogProductView->open();
 
-        //Process assertions
-        $this->assertOnProductView($catalogProductView);
+        $data = $this->prepareData($catalogProductView);
+        $badValues = array_diff($data['onPage'], $data['fixture']);
+        $errors = array_intersect_key($this->errorsMessages, array_keys($badValues));
+        $errors += $this->verifySpecialPrice($catalogProductView);
+        \PHPUnit_Framework_Assert::assertEmpty(
+            $errors,
+            PHP_EOL . 'Found the following errors:' . PHP_EOL . implode(' ' . PHP_EOL, $this->errorsMessages)
+        );
     }
 
     /**
-     * Assert prices on the product view page
+     * Prepare array for assert
      *
      * @param CatalogProductView $catalogProductView
-     * @return void
+     * @return array
      */
-    protected function assertOnProductView(CatalogProductView $catalogProductView)
+    protected function prepareData(CatalogProductView $catalogProductView)
     {
         $viewBlock = $catalogProductView->getViewBlock();
         $price = $viewBlock->getProductPriceBlock()->getPrice();
-        $errorsMessages = [
-            'name'              => '- product name on product view page is not correct.',
-            'sku'               => '- product sku on product view page is not correct.',
-            'regular_price'     => '- product regular price on product view page is not correct.',
-            'short_description' => '- product short description on product view page is not correct.',
-            'description'       => '- product description on product view page is not correct.'
-        ];
-        $dataOnPage = [
-            'name'          => $viewBlock->getProductName(),
-            'sku'           => $viewBlock->getProductSku(),
-            'regular_price' => $price['price_regular_price']
+        $data = [
+            'onPage' => [
+                'name' => $viewBlock->getProductName(),
+                'sku' => $viewBlock->getProductSku(),
+            ],
+            'fixture' => [
+                'name' => $this->product->getName(),
+                'sku' => $this->product->getSku(),
+            ]
         ];
-        $compareData = [
-            'name'          => $this->product->getName(),
-            'sku'           => $this->product->getSku(),
-            'regular_price' => number_format($this->product->getPrice(), 2),
 
-        ];
+        list($priceOnPage, $priceFixture) = $this->preparePrice($price);
+        $data['onPage'] += $priceOnPage;
+        $data['fixture'] += $priceFixture;
 
         if ($productShortDescription = $this->product->getShortDescription()) {
-            $compareData['short_description'] = $productShortDescription;
-            $dataOnPage['short_description'] = $viewBlock->getProductShortDescription();
+            $data['fixture']['short_description'] = $productShortDescription;
+            $data['onPage']['short_description'] = $viewBlock->getProductShortDescription();
         }
         if ($productDescription = $this->product->getDescription()) {
-            $compareData['description'] = $productDescription;
-            $dataOnPage['description'] = $viewBlock->getProductDescription();
+            $data['fixture']['description'] = $productDescription;
+            $data['onPage']['description'] = $viewBlock->getProductDescription();
         }
 
-        $badValues = array_diff($dataOnPage, $compareData);
-        $errorsMessages = array_merge(
-            $this->assertSpecialPrice($price),
-            array_intersect_key($errorsMessages, array_keys($badValues))
-        );
+        return $data;
+    }
 
-        \PHPUnit_Framework_Assert::assertTrue(
-            empty($errorsMessages),
-            PHP_EOL . 'Found the following errors:' . PHP_EOL
-            . implode(' ' . PHP_EOL, $errorsMessages)
-        );
+    /**
+     * Prepare Price data
+     *
+     * @param array $price
+     * @return array
+     */
+    protected function preparePrice($price)
+    {
+        return [
+            ['regular_price' => $price['price_regular_price']],
+            ['regular_price' => number_format($this->product->getPrice(), 2)]
+        ];
     }
 
     /**
      * Checking the special product price
      *
-     * @param array $price
+     * @param CatalogProductView $catalogProductView
      * @return array
      */
-    protected function assertSpecialPrice(array $price)
+    protected function verifySpecialPrice(CatalogProductView $catalogProductView)
     {
+        $priceBlock = $catalogProductView->getViewBlock()->getProductPriceBlock();
+        $price = $priceBlock->isVisible() ? $priceBlock->getPrice() : ['price_special_price' => null];
         $priceComparing = false;
+
         if ($specialPrice = $this->product->getSpecialPrice()) {
             $priceComparing = $specialPrice;
         }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSaveMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSaveMessage.php
index 0c0795556a4689a9d383aaaf59e39206e8a12ac2..8af6a38dad20e853f615b11282116b7324259fea 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSaveMessage.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSaveMessage.php
@@ -52,18 +52,19 @@ class AssertProductSaveMessage extends AbstractConstraint
      */
     public function processAssert(CatalogProductEdit $productPage)
     {
-        $actualMessage = $productPage->getMessagesBlock()->getSuccessMessages();
-        \PHPUnit_Framework_Assert::assertEquals(
+        $actualMessages = $productPage->getMessagesBlock()->getSuccessMessages();
+        $actualMessages = is_array($actualMessages) ? $actualMessages : [$actualMessages];
+        \PHPUnit_Framework_Assert::assertContains(
             self::SUCCESS_MESSAGE,
-            $actualMessage,
+            $actualMessages,
             'Wrong success message is displayed.'
             . "\nExpected: " . self::SUCCESS_MESSAGE
-            . "\nActual: " . $actualMessage
+            . "\nActual:\n" . implode("\n - ", $actualMessages)
         );
     }
 
     /**
-     * Returns a string representation of the object.
+     * Returns a string representation of the object
      *
      * @return string
      */
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSearchableBySku.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSearchableBySku.php
index ffd5b5de0a9e36ca4cc085ffaf67dfd7255b62b9..db48a737ccb5304039e03ac5201328fc3d4b061c 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSearchableBySku.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSearchableBySku.php
@@ -62,6 +62,8 @@ class AssertProductSearchableBySku extends AbstractConstraint
      * @param CmsIndex $cmsIndex
      * @param FixtureInterface $product
      * @return void
+     *
+     * @SuppressWarnings(PHPMD.NPathComplexity)
      */
     public function processAssert(
         CatalogsearchResult $catalogSearchResult,
@@ -69,19 +71,24 @@ class AssertProductSearchableBySku extends AbstractConstraint
         FixtureInterface $product
     ) {
         $cmsIndex->open();
-        $cmsIndex->getSearchBlock()->search($product->getSku());
+        $sku = ($product->hasData('sku') !== false) ? $product->getSku() : $product->getName();
+        $cmsIndex->getSearchBlock()->search($sku);
+
+        $quantityAndStockStatus = $product->getQuantityAndStockStatus();
+        $stockStatus = isset($quantityAndStockStatus['is_in_stock'])
+            ? $quantityAndStockStatus['is_in_stock']
+            : null;
 
-        $isInStock = $product->getQuantityAndStockStatus();
-        if ($product->getVisibility() === 'Catalog'
-            || (isset($isInStock['is_in_stock']) && $isInStock['is_in_stock'] === 'Out of Stock')
-        ) {
-            $isVisible = !($catalogSearchResult->getListProductBlock()->isProductVisible($product->getName()));
-            $this->errorMessage = 'Product successfully found by SKU.';
-            $this->successfulMessage = 'The product has not been found by SKU.';
-        } else {
+        $isVisible = $catalogSearchResult->getListProductBlock()->isProductVisible($product->getName());
+        while (!$isVisible && $catalogSearchResult->getToolbar()->nextPage()) {
             $isVisible = $catalogSearchResult->getListProductBlock()->isProductVisible($product->getName());
         }
 
+        if ($product->getVisibility() === 'Catalog' || $stockStatus === 'Out of Stock') {
+            $isVisible = !$isVisible;
+            list($this->errorMessage, $this->successfulMessage) = [$this->successfulMessage, $this->errorMessage];
+        }
+
         \PHPUnit_Framework_Assert::assertTrue(
             $isVisible,
             $this->errorMessage
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSimpleDuplicateForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSimpleDuplicateForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..b0975294e6d1a56631974f5241c828d1c363e652
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSimpleDuplicateForm.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+/**
+ * Class AssertProductSimpleDuplicateForm
+ * Assert form data equals duplicate simple product data
+ */
+class AssertProductSimpleDuplicateForm extends AssertProductDuplicateForm
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertSpecialPriceOnProductPage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSpecialPriceOnProductPage.php
old mode 100644
new mode 100755
similarity index 63%
rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertSpecialPriceOnProductPage.php
rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSpecialPriceOnProductPage.php
index aa17ed49c67a0efc500eac2e9e2e31805e54a29d..39561809d3dd2fb91d5bcb0fff0555e0f9cbbb7b
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertSpecialPriceOnProductPage.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSpecialPriceOnProductPage.php
@@ -29,9 +29,9 @@ use Mtf\Constraint\AbstractConstraint;
 use Magento\Catalog\Test\Page\Product\CatalogProductView;
 
 /**
- * Class AssertSpecialPriceOnProductPage
+ * Class AssertProductSpecialPriceOnProductPage
  */
-class AssertSpecialPriceOnProductPage extends AbstractConstraint
+class AssertProductSpecialPriceOnProductPage extends AbstractConstraint implements AssertPriceOnProductPageInterface
 {
     /**
      * Constraint severeness
@@ -40,6 +40,13 @@ class AssertSpecialPriceOnProductPage extends AbstractConstraint
      */
     protected $severeness = 'low';
 
+    /**
+     * Error message
+     *
+     * @var string
+     */
+    protected $errorMessage = 'Assert that displayed special price on product page NOT equals to passed from fixture.';
+
     /**
      * Assert that displayed special price on product page equals passed from fixture
      *
@@ -51,16 +58,45 @@ class AssertSpecialPriceOnProductPage extends AbstractConstraint
     {
         $catalogProductView->init($product);
         $catalogProductView->open();
+
+        //Process assertions
+        $this->assertPrice($product, $catalogProductView);
+    }
+
+    /**
+     * Set $errorMessage for special price assert
+     *
+     * @param string $errorMessage
+     * @return void
+     */
+    public function setErrorMessage($errorMessage)
+    {
+        $this->errorMessage = $errorMessage;
+    }
+
+    /**
+     * Verify product special price on product view page
+     *
+     * @param CatalogProductView $catalogProductView
+     * @param FixtureInterface $product
+     * @param string $block [optional]
+     * @return void
+     */
+    public function assertPrice(
+        FixtureInterface $product,
+        CatalogProductView $catalogProductView,
+        $block = ''
+    ) {
         $fields = $product->getData();
-        $specialPrice = $catalogProductView->getViewBlock()->getProductPrice();
+        $specialPrice = $catalogProductView->{'get' . $block . 'ViewBlock'}()->getProductPrice();
         $specialPrice = (isset($specialPrice['price_special_price']))
             ? $specialPrice['price_special_price']
             : null;
         if (isset($fields['special_price'])) {
             \PHPUnit_Framework_Assert::assertEquals(
-                $fields['special_price'],
+                number_format($fields['special_price'], 2),
                 $specialPrice,
-                'Assert that displayed special price on product page NOT equals passed from fixture.'
+                $this->errorMessage
             );
         }
     }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateGroupOnProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateGroupOnProductForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..492294e88edf27cb4b8ed7106fa138b355cb0e4b
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateGroupOnProductForm.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Fixture\FixtureFactory;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Fixture\CatalogAttributeSet;
+use Magento\Catalog\Test\Fixture\CatalogProductSimple;
+use Magento\Catalog\Test\Fixture\CatalogProductAttribute;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+
+/**
+ * Class AssertProductTemplateGroupOnProductForm
+ * Check that created product template displays in product template suggest container dropdown and
+ * can be used for new created product
+ */
+class AssertProductTemplateGroupOnProductForm extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'high';
+
+    /**
+     * Assert that created product template:
+     * 1. Displays in product template suggest container dropdown
+     * 2. Can be used for new created product.
+     *
+     * @param FixtureFactory $fixtureFactory
+     * @param CatalogProductEdit $productEdit
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogAttributeSet $attributeSet
+     * @param CatalogProductNew $newProductPage
+     * @param CatalogProductAttribute $productAttributeOriginal
+     * @return void
+     */
+    public function processAssert
+    (
+        FixtureFactory $fixtureFactory,
+        CatalogProductEdit $productEdit,
+        CatalogProductIndex $productGrid,
+        CatalogAttributeSet $attributeSet,
+        CatalogProductNew $newProductPage,
+        CatalogProductAttribute $productAttributeOriginal
+    ) {
+
+        $productGrid->open();
+        $productGrid->getGridPageActionBlock()->addProduct('simple');
+        $productBlockForm = $newProductPage->getForm();
+
+        /**@var CatalogProductSimple $catalogProductSimple */
+        $productSimple = $fixtureFactory->createByCode(
+            'catalogProductSimple',
+            [
+                'dataSet' => 'default',
+                'data' => [
+                    'attribute_set_id' => ['attribute_set' => $attributeSet],
+                ],
+            ]
+        );
+        $productBlockForm->fill($productSimple);
+
+        \PHPUnit_Framework_Assert::assertTrue(
+            $productEdit->getForm()->isTabVisible($attributeSet->getGroup()),
+            "Product Group is absent on Product form tabs."
+        );
+
+        $productEdit->getForm()->openCustomTab($attributeSet->getGroup());
+        \PHPUnit_Framework_Assert::assertTrue(
+            $productEdit->getForm()->checkAttributeLabel($productAttributeOriginal),
+            "Product Attribute is absent on Product form."
+        );
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Product Group and Product Attribute are present on the Product form.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateNotInGrid.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateNotInGrid.php
new file mode 100644
index 0000000000000000000000000000000000000000..36a9580890c8a7638abe7f007bd3608fb536089b
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateNotInGrid.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Fixture\CatalogAttributeSet;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex;
+
+/**
+ * Class AssertProductTemplateNotInGrid
+ * Assert that Product Template absence on grid
+ */
+class AssertProductTemplateNotInGrid extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert that product template is not displayed in Product Templates grid
+     *
+     * @param CatalogProductSetIndex $productSetPage
+     * @param CatalogAttributeSet $productTemplate
+     * @return void
+     */
+    public function processAssert(CatalogProductSetIndex $productSetPage, CatalogAttributeSet $productTemplate)
+    {
+        $filterAttributeSet = [
+            'set_name' => $productTemplate->getAttributeSetName(),
+        ];
+
+        $productSetPage->open();
+        \PHPUnit_Framework_Assert::assertFalse(
+            $productSetPage->getGrid()->isRowVisible($filterAttributeSet),
+            'Attribute Set with name "' . $filterAttributeSet['set_name'] . '" is present in Product Template grid.'
+        );
+    }
+
+    /**
+     * Text absent new product template in grid
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Product template is absent in Product Templates grid';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateOnProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateOnProductForm.php
old mode 100644
new mode 100755
index 3d7b29e55d6d797283d8cc9fb16b1dad7a7e954c..c0b365a1e1f37069ca6d93c4523cc086d5f134f8
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateOnProductForm.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateOnProductForm.php
@@ -55,6 +55,7 @@ class AssertProductTemplateOnProductForm extends AbstractConstraint
      * @param CatalogProductEdit $productEdit
      * @param CatalogProductIndex $productGrid
      * @param CatalogAttributeSet $attributeSet
+     * @param CatalogAttributeSet $attributeSetOriginal
      * @param CatalogProductNew $newProductPage
      * @param CatalogProductAttribute $productAttribute
      * @return void
@@ -66,11 +67,12 @@ class AssertProductTemplateOnProductForm extends AbstractConstraint
         CatalogProductIndex $productGrid,
         CatalogAttributeSet $attributeSet,
         CatalogProductNew $newProductPage,
-        CatalogProductAttribute $productAttribute
+        CatalogProductAttribute $productAttribute,
+        CatalogAttributeSet $attributeSetOriginal = null
     ) {
 
         $productGrid->open();
-        $productGrid->getProductBlock()->addProduct('simple');
+        $productGrid->getGridPageActionBlock()->addProduct('simple');
         $productBlockForm = $newProductPage->getForm();
 
         /**@var CatalogProductSimple $catalogProductSimple */
@@ -83,7 +85,7 @@ class AssertProductTemplateOnProductForm extends AbstractConstraint
                 ],
             ]
         );
-        $productBlockForm->fillProduct($productSimple);
+        $productBlockForm->fill($productSimple);
         $newProductPage->getFormAction()->save();
 
         $formData = $productEdit->getForm()->getData($productSimple);
@@ -96,11 +98,14 @@ class AssertProductTemplateOnProductForm extends AbstractConstraint
             . "\nActual: " . $formAttributeSet
         );
 
-        $productEdit->getForm()->openTab('product-details');
-        \PHPUnit_Framework_Assert::assertTrue(
-            $productEdit->getForm()->checkAttributeLabel($productAttribute),
-            "Product Attribute is absent on Product form."
-        );
+        if ($attributeSetOriginal === null) {
+            $productEdit->getForm()->openTab('product-details');
+
+            \PHPUnit_Framework_Assert::assertTrue(
+                $productEdit->getForm()->checkAttributeLabel($productAttribute),
+                "Product Attribute is absent on Product form."
+            );
+        }
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateSuccessDeleteMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..d794de682bbe29151d54e70974e4905d53f378e0
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateSuccessDeleteMessage.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex;
+
+/**
+ * Class AssertProductTemplateSuccessDeleteMessage
+ * Check Product Templates success delete message
+ */
+class AssertProductTemplateSuccessDeleteMessage extends AbstractConstraint
+{
+    /**
+     * Text value to be checked
+     */
+    const SUCCESS_DELETE_MESSAGE = 'The attribute set has been removed.';
+
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'high';
+
+    /**
+     * Assert that after deleting product template success delete message appears
+     *
+     * @param CatalogProductSetIndex $productSetIndex
+     * @return void
+     */
+    public function processAssert(CatalogProductSetIndex $productSetIndex)
+    {
+        $actualMessage = $productSetIndex->getMessagesBlock()->getSuccessMessages();
+        \PHPUnit_Framework_Assert::assertEquals(
+            self::SUCCESS_DELETE_MESSAGE,
+            $actualMessage,
+            'Wrong success message is displayed.'
+            . "\nExpected: " . self::SUCCESS_DELETE_MESSAGE
+            . "\nActual: " . $actualMessage
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Product Templates success delete message is present.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertTierPriceOnProductPage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTierPriceOnProductPage.php
old mode 100644
new mode 100755
similarity index 71%
rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertTierPriceOnProductPage.php
rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTierPriceOnProductPage.php
index d2cf9dfba5c80ba8c7429f6c51e2ac1d827f4cb1..da02ab532058870322ac3a40292862923726fd36
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertTierPriceOnProductPage.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTierPriceOnProductPage.php
@@ -27,11 +27,12 @@ namespace Magento\Catalog\Test\Constraint;
 use Mtf\Fixture\FixtureInterface;
 use Mtf\Constraint\AbstractConstraint;
 use Magento\Catalog\Test\Page\Product\CatalogProductView;
+use Magento\Catalog\Test\Block\Product\View;
 
 /**
- * Class AssertTierPriceOnProductPage
+ * Class AssertProductTierPriceOnProductPage
  */
-class AssertTierPriceOnProductPage extends AbstractConstraint
+class AssertProductTierPriceOnProductPage extends AbstractConstraint implements AssertPriceOnProductPageInterface
 {
     /**
      * Constraint severeness
@@ -40,6 +41,20 @@ class AssertTierPriceOnProductPage extends AbstractConstraint
      */
     protected $severeness = 'low';
 
+    /**
+     * Error message
+     *
+     * @var string
+     */
+    protected $errorMessage = 'Product tier price on product page is not correct.';
+
+    /**
+     * Format price
+     *
+     * @var int
+     */
+    protected $priceFormat = 2;
+
     /**
      * Assertion that tier prices are displayed correctly
      *
@@ -57,7 +72,18 @@ class AssertTierPriceOnProductPage extends AbstractConstraint
         $catalogProductView->open();
 
         //Process assertions
-        $this->assertTierPrice($product, $catalogProductView);
+        $this->assertPrice($product, $catalogProductView);
+    }
+
+    /**
+     * Set $errorMessage for tier price assert
+     *
+     * @param string $errorMessage
+     * @return void
+     */
+    public function setErrorMessage($errorMessage)
+    {
+        $this->errorMessage = $errorMessage;
     }
 
     /**
@@ -65,14 +91,16 @@ class AssertTierPriceOnProductPage extends AbstractConstraint
      *
      * @param FixtureInterface $product
      * @param CatalogProductView $catalogProductView
+     * @param string $block [optional]
      * @return void
      */
-    protected function assertTierPrice(FixtureInterface $product, CatalogProductView $catalogProductView)
+    public function assertPrice(FixtureInterface $product, CatalogProductView $catalogProductView, $block = '')
     {
         $noError = true;
         $match = [];
         $index = 1;
-        $viewBlock = $catalogProductView->getViewBlock();
+        /** @var View $viewBlock */
+        $viewBlock = $catalogProductView->{'get' . $block . 'ViewBlock'}();
         $tierPrices = $product->getTierPrice();
 
         foreach ($tierPrices as $tierPrice) {
@@ -83,14 +111,14 @@ class AssertTierPriceOnProductPage extends AbstractConstraint
             }
             if (count($match) < 2
                 && $match[1] != $tierPrice['price_qty']
-                || $match[2] !== number_format($tierPrice['price'], 2)
+                || $match[2] !== number_format($tierPrice['price'], $this->priceFormat)
             ) {
                 $noError = false;
                 break;
             }
         }
 
-        \PHPUnit_Framework_Assert::assertTrue($noError, 'Product tier price on product page is not correct.');
+        \PHPUnit_Framework_Assert::assertTrue($noError, $this->errorMessage);
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductVisibleInCategory.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductVisibleInCategory.php
index 04e4727a32ffc6be3c8e3dc718234470c1622e93..da0b9f38421d5ba5bd128b865cb63868f9c89fb0 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductVisibleInCategory.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductVisibleInCategory.php
@@ -42,7 +42,6 @@ class AssertProductVisibleInCategory extends AbstractConstraint
      */
     protected $severeness = 'low';
 
-
     /**
      * Displays an error message
      *
@@ -63,27 +62,27 @@ class AssertProductVisibleInCategory extends AbstractConstraint
      * @param CatalogCategoryView $catalogCategoryView
      * @param CmsIndex $cmsIndex
      * @param FixtureInterface $product
-     * @param CatalogCategory $category
+     * @param CatalogCategory|null $category
      * @return void
+     *
+     * @SuppressWarnings(PHPMD.NPathComplexity)
      */
     public function processAssert(
         CatalogCategoryView $catalogCategoryView,
         CmsIndex $cmsIndex,
         FixtureInterface $product,
-        CatalogCategory $category
+        CatalogCategory $category = null
     ) {
+        $categoryName = $product->hasData('category_ids') ? $product->getCategoryIds()[0] : $category->getName();
         $cmsIndex->open();
-        $cmsIndex->getTopmenu()->selectCategoryByName($category->getName());
+        $cmsIndex->getTopmenu()->selectCategoryByName($categoryName);
 
         $isProductVisible = $catalogCategoryView->getListProductBlock()->isProductVisible($product->getName());
         while (!$isProductVisible && $catalogCategoryView->getToolbar()->nextPage()) {
             $isProductVisible = $catalogCategoryView->getListProductBlock()->isProductVisible($product->getName());
         }
 
-        $isInStock = $product->getQuantityAndStockStatus();
-        if ($product->getVisibility() === 'Search'
-            || (isset($isInStock['is_in_stock']) && $isInStock['is_in_stock'] === 'Out of Stock')
-        ) {
+        if (($product->getVisibility() === 'Search') || ($this->getStockStatus($product) === 'Out of Stock')) {
             $isProductVisible = !$isProductVisible;
             $this->errorMessage = 'Product found in this category.';
             $this->successfulMessage = 'Asserts that the product could not be found in this category.';
@@ -95,6 +94,18 @@ class AssertProductVisibleInCategory extends AbstractConstraint
         );
     }
 
+    /**
+     * Getting is in stock status
+     *
+     * @param FixtureInterface $product
+     * @return string|null
+     */
+    protected function getStockStatus(FixtureInterface $product)
+    {
+        $quantityAndStockStatus = $product->getQuantityAndStockStatus();
+        return isset($quantityAndStockStatus['is_in_stock']) ? $quantityAndStockStatus['is_in_stock'] : null;
+    }
+
     /**
      * Returns a string representation of the object
      *
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertRelatedProductsSection.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertRelatedProductsSection.php
old mode 100644
new mode 100755
index 99cb9c60ebbf578a90a72d9c0def7d26407f49be..5448c74e9a5167efa265b09c9a4c56de946025d9
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertRelatedProductsSection.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertRelatedProductsSection.php
@@ -59,7 +59,7 @@ class AssertRelatedProductsSection extends AbstractConstraint
         CatalogCategoryView $catalogCategoryView,
         CatalogProductView $catalogProductView
     ) {
-        $categoryName = $product1->getCategoryIds()[0]['name'];
+        $categoryName = $product1->getCategoryIds()[0];
         $cmsIndex->open();
         $cmsIndex->getTopmenu()->selectCategoryByName($categoryName);
         $catalogCategoryView->getListProductBlock()->openProductViewPage($product1->getName());
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertUpSellsProductsSection.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertUpSellsProductsSection.php
old mode 100644
new mode 100755
index 9a90a23493e32967856e059417a2af23e906286f..bc6d87abcce1be69c1eeacaa7bec5ddca87b2c95
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertUpSellsProductsSection.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertUpSellsProductsSection.php
@@ -59,7 +59,7 @@ class AssertUpSellsProductsSection extends AbstractConstraint
         CatalogCategoryView $catalogCategoryView,
         CatalogProductView $catalogProductView
     ) {
-        $categoryName = $product1->getCategoryIds()[0]['name'];
+        $categoryName = $product1->getCategoryIds()[0];
         $cmsIndex->open();
         $cmsIndex->getTopmenu()->selectCategoryByName($categoryName);
         $catalogCategoryView->getListProductBlock()->openProductViewPage($product1->getName());
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogAttributeSet.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogAttributeSet.php
index 85942bbc2a98021925cd40747d542838ba108324..e5ed3b548087a977907e3344f4f70f0215e31d5a 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogAttributeSet.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogAttributeSet.php
@@ -27,8 +27,8 @@ namespace Magento\Catalog\Test\Fixture;
 use Mtf\Fixture\InjectableFixture;
 
 /**
- * Class CatalogProductTemplate
- * Product Template fixture
+ * Class CatalogAttributeSet
+ * Catalog Attribute Set fixture
  */
 class CatalogAttributeSet extends InjectableFixture
 {
@@ -88,6 +88,17 @@ class CatalogAttributeSet extends InjectableFixture
         'source' => 'Magento\Catalog\Test\Fixture\CatalogAttributeSet\SkeletonSet',
     ];
 
+    protected $assigned_attributes = [
+        'attribute_code' => 'assigned_attributes',
+        'backend_type' => 'virtual',
+        'source' => 'Magento\Catalog\Test\Fixture\CatalogAttributeSet\AssignedAttributes',
+    ];
+
+    protected $group = [
+        'attribute_code' => 'group',
+        'backend_type' => 'virtual',
+    ];
+
     public function getAttributeSetId()
     {
         return $this->getData('attribute_set_id');
@@ -112,4 +123,14 @@ class CatalogAttributeSet extends InjectableFixture
     {
         return $this->getData('skeleton_set');
     }
+
+    public function getAssignedAttributes()
+    {
+        return $this->getData('assigned_attributes');
+    }
+
+    public function getGroup()
+    {
+        return $this->getData('group');
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogAttributeSet.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogAttributeSet.xml
index 9d89dbd3824e0585791ecfa3894204d56f4b51db..5cdb82ee1414c1e11cfe4608aae2e5f3921c807a 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogAttributeSet.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogAttributeSet.xml
@@ -61,6 +61,15 @@
             <attribute_code>skeleton_set</attribute_code>
             <backend_type>virtual</backend_type>
         </skeleton_set>
+        <assigned_attributes>
+            <attribute_code>assigned_attributes</attribute_code>
+            <backend_type>virtual</backend_type>
+            <source>Magento\Catalog\Test\Fixture\CatalogAttributeSet\AssignedAttributes</source>
+        </assigned_attributes>
+        <group>
+            <attribute_code>group</attribute_code>
+            <backend_type>virtual</backend_type>
+        </group>
     </fields>
     <repository_class>Magento\Catalog\Test\Repository\CatalogAttributeSet</repository_class>
     <handler_interface>Magento\Catalog\Test\Handler\CatalogAttributeSet\CatalogAttributeSetInterface</handler_interface>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogAttributeSet/AssignedAttributes.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogAttributeSet/AssignedAttributes.php
new file mode 100644
index 0000000000000000000000000000000000000000..49576b99733f8c4fa70549d36c255d4e5a7e2899
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogAttributeSet/AssignedAttributes.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Fixture\CatalogAttributeSet;
+
+use Mtf\Fixture\FixtureFactory;
+use Mtf\Fixture\FixtureInterface;
+use Magento\Catalog\Test\Fixture\CatalogProductAttribute;
+
+/**
+ * Class AssignedAttributes
+ *
+ *  Data keys:
+ *  - presets
+ */
+class AssignedAttributes implements FixtureInterface
+{
+    /**
+     * Data set configuration settings
+     *
+     * @var array
+     */
+    protected $params = [];
+
+    /**
+     * Names of assigned attributes
+     *
+     * @var array
+     */
+    protected $data = [];
+
+    /**
+     * Assigned attributes
+     *
+     * @var array
+     */
+    protected $attributes = [];
+
+    /**
+     * @constructor
+     * @param FixtureFactory $fixtureFactory
+     * @param array $params
+     * @param array $data [optional]
+     */
+    public function __construct(FixtureFactory $fixtureFactory, array $params, array $data = [])
+    {
+        $this->params = $params;
+        if (isset($data['presets']) && $data['presets'] !== '-') {
+            $presets = explode(',', $data['presets']);
+            foreach ($presets as $preset) {
+                /** @var CatalogProductAttribute $attribute */
+                $attribute = $fixtureFactory->createByCode('catalogProductAttribute', ['dataSet' => $preset]);
+                $attribute->persist();
+
+                $this->data[] = $attribute->getAttributeCode();
+                $this->attributes[] = $attribute;
+            }
+        } else {
+            $this->data = $data;
+        }
+    }
+
+    /**
+     * Persist attribute
+     *
+     * @return void
+     */
+    public function persist()
+    {
+        //
+    }
+
+    /**
+     * Return data set configuration settings
+     *
+     * @return array
+     */
+    public function getDataConfig()
+    {
+        return $this->params;
+    }
+
+    /**
+     * Return prepared data set
+     *
+     * @param string|null $key
+     * @return array
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function getData($key = null)
+    {
+        return $this->data;
+    }
+
+    /**
+     * Get Attributes
+     *
+     * @return array
+     */
+    public function getAttributes()
+    {
+        return $this->attributes;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory.php
index dff2a59d98b510f5edd81bcf26f30c21cb592d4c..29ec7ec1e25293b34ce4572b360437f3a16fac7c 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory.php
@@ -197,21 +197,39 @@ class CatalogCategory extends InjectableFixture
     protected $name = [
         'attribute_code' => 'name',
         'backend_type' => 'virtual',
+        'group' => 'general_information',
     ];
 
     protected $is_active = [
         'attribute_code' => 'is_active',
         'backend_type' => 'virtual',
+        'group' => 'general_information',
     ];
 
     protected $url_key = [
         'attribute_code' => 'url_key',
         'backend_type' => 'virtual',
+        'group' => 'general_information',
     ];
 
     protected $include_in_menu = [
         'attribute_code' => 'include_in_menu',
         'backend_type' => 'virtual',
+        'group' => 'general_information',
+    ];
+
+    protected $landing_page = [
+        'attribute_code' => 'landing_page',
+        'backend_type' => 'virtual',
+        'input' => 'select',
+        'group' => 'display_setting',
+    ];
+
+    protected $display_mode = [
+        'attribute_code' => 'display_mode',
+        'backend_type' => 'virtual',
+        'input' => 'select',
+        'group' => 'display_setting',
     ];
 
     protected $category_products = [
@@ -326,8 +344,23 @@ class CatalogCategory extends InjectableFixture
         return $this->getData('include_in_menu');
     }
 
+    public function getLandingPage()
+    {
+        return $this->getData('landing_page');
+    }
+
+    public function getDisplayMode()
+    {
+        return $this->getData('display_mode');
+    }
+
     public function getCategoryProducts()
     {
         return $this->getData('category_products');
     }
+
+    public function getBlockId()
+    {
+        return $this->getData('block_id');
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory.xml
index ab2369fc54af0e76b01621345ca730fc3fe90525..ef393c01c95bfc650cee70128569d88b7d7d7c33 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory.xml
@@ -149,19 +149,35 @@
         <name>
             <attribute_code>name</attribute_code>
             <backend_type>virtual</backend_type>
+            <group>general_information</group>
         </name>
         <is_active>
             <attribute_code>is_active</attribute_code>
             <backend_type>virtual</backend_type>
+            <group>general_information</group>
         </is_active>
         <url_key>
             <attribute_code>url_key</attribute_code>
             <backend_type>virtual</backend_type>
+            <group>general_information</group>
         </url_key>
         <include_in_menu>
             <attribute_code>include_in_menu</attribute_code>
             <backend_type>virtual</backend_type>
+            <group>general_information</group>
         </include_in_menu>
+        <landing_page>
+            <attribute_code>landing_page</attribute_code>
+            <backend_type>virtual</backend_type>
+            <input>select</input>
+            <group>display_setting</group>
+        </landing_page>
+        <display_mode>
+            <attribute_code>display_mode</attribute_code>
+            <backend_type>virtual</backend_type>
+            <input>select</input>
+            <group>display_setting</group>
+        </display_mode>
         <category_products>
             <attribute_code>category_products</attribute_code>
             <backend_type>virtual</backend_type>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.php
old mode 100644
new mode 100755
index 67590d6d8dc3cf08678141cc7f9795ed16ad152c..d34ea99c6890949d5783cada18d268ebab3ae4ed
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.php
@@ -106,6 +106,7 @@ class CatalogProductSimple extends InjectableFixture
             'qty' => 10.0000,
             'is_in_stock' => 'In Stock',
         ],
+        'website_ids' => ['Main Website'],
     ];
 
     protected $category_ids = [
@@ -114,6 +115,7 @@ class CatalogProductSimple extends InjectableFixture
         'is_required' => '0',
         'default_value' => '',
         'input' => 'text',
+        'group' => 'product-details',
         'source' => 'Magento\Catalog\Test\Fixture\CatalogProductSimple\CategoryIds',
     ];
 
@@ -324,22 +326,6 @@ class CatalogProductSimple extends InjectableFixture
         'group' => 'product-details',
     ];
 
-    protected $news_from_date = [
-        'attribute_code' => 'news_from_date',
-        'backend_type' => 'datetime',
-        'is_required' => '0',
-        'default_value' => '',
-        'input' => 'date',
-    ];
-
-    protected $news_to_date = [
-        'attribute_code' => 'news_to_date',
-        'backend_type' => 'datetime',
-        'is_required' => '0',
-        'default_value' => '',
-        'input' => 'date',
-    ];
-
     protected $old_id = [
         'attribute_code' => 'old_id',
         'backend_type' => 'int',
@@ -376,10 +362,10 @@ class CatalogProductSimple extends InjectableFixture
 
     protected $quantity_and_stock_status = [
         'attribute_code' => 'quantity_and_stock_status',
-        'backend_type' => 'int',
+        'backend_type' => 'array',
         'is_required' => '0',
-        'default_value' => 'In Stock',
-        'input' => 'select',
+        'default_value' => '',
+        'input' => '',
         'group' => 'product-details',
     ];
 
@@ -574,10 +560,37 @@ class CatalogProductSimple extends InjectableFixture
     protected $website_ids = [
         'attribute_code' => 'website_ids',
         'backend_type' => 'virtual',
-        'default_value' => ['Main Website'],
+        'default_value' => 'Main Website',
         'group' => 'websites',
     ];
 
+    protected $is_returnable = [
+        'attribute_code' => 'is_returnable',
+        'backend_type' => 'varchar',
+        'is_required' => '0',
+        'default_value' => '2',
+        'input' => 'select',
+        'group' => 'autosettings',
+    ];
+
+    protected $news_from_date = [
+        'attribute_code' => 'news_from_date',
+        'backend_type' => 'datetime',
+        'is_required' => '0',
+        'default_value' => '',
+        'input' => 'date',
+        'source' => 'Magento\Backend\Test\Fixture\Date',
+    ];
+
+    protected $news_to_date = [
+        'attribute_code' => 'news_to_date',
+        'backend_type' => 'datetime',
+        'is_required' => '0',
+        'default_value' => '',
+        'input' => 'date',
+        'source' => 'Magento\Backend\Test\Fixture\Date',
+    ];
+
     public function getCategoryIds()
     {
         return $this->getData('category_ids');
@@ -708,16 +721,6 @@ class CatalogProductSimple extends InjectableFixture
         return $this->getData('name');
     }
 
-    public function getNewsFromDate()
-    {
-        return $this->getData('news_from_date');
-    }
-
-    public function getNewsToDate()
-    {
-        return $this->getData('news_to_date');
-    }
-
     public function getOldId()
     {
         return $this->getData('old_id');
@@ -862,4 +865,19 @@ class CatalogProductSimple extends InjectableFixture
     {
         return $this->getData('website_ids');
     }
+
+    public function getIsReturnable()
+    {
+        return $this->getData('is_returnable');
+    }
+
+    public function getNewsFromDate()
+    {
+        return $this->getData('news_from_date');
+    }
+
+    public function getNewsToDate()
+    {
+        return $this->getData('news_to_date');
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml
old mode 100644
new mode 100755
index feccbc686956427730064ba45598084b355eea1f..52b9547ef7ff82391d79a5c3d2b3473d520eb9ef
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml
@@ -37,7 +37,8 @@
             <is_required>0</is_required>
             <default_value></default_value>
             <input>text</input>
-            <fixture>Magento\Catalog\Test\Fixture\CatalogProductSimple\CategoryIds</fixture>
+            <group>product-details</group>
+            <source>Magento\Catalog\Test\Fixture\CatalogProductSimple\CategoryIds</source>
         </category_ids>
         <color>
             <attribute_code>color</attribute_code>
@@ -445,6 +446,14 @@
             <default_value>Main Website</default_value>
             <group>websites</group>
         </website_ids>
+        <is_returnable>
+            <attribute_code>is_returnable</attribute_code>
+            <backend_type>varchar</backend_type>
+            <is_required>0</is_required>
+            <default_value>2</default_value>
+            <input>select</input>
+            <group>autosettings</group>
+        </is_returnable>
     </fields>
     <data_set>
         <sku></sku>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CategoryIds.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CategoryIds.php
old mode 100644
new mode 100755
index a8b463e1fdf4cca4a4a8d1af724f0157de4110a3..ec2f5b38f454b0418d95599ab2ddb8f784f9d115
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CategoryIds.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CategoryIds.php
@@ -42,13 +42,14 @@ class CategoryIds implements FixtureInterface
     protected $data;
 
     /**
-     * New categories
+     * Fixtures of category
      *
      * @var array
      */
-    protected $category;
+    protected $categories;
 
     /**
+     * @constructor
      * @param FixtureFactory $fixtureFactory
      * @param array $params
      * @param array $data
@@ -66,24 +67,20 @@ class CategoryIds implements FixtureInterface
         ) {
             /** @var CatalogCategory $category */
             $category = $data['category'];
-            $this->data[] = [
-                'id' => $category->getId(),
-                'name' => $category->getName(),
-            ];
-            $this->category[] = $category;
-        } elseif (isset($data['presets']) && $data['presets'] !== '-') {
-
+            if (!$category->hasData('id')) {
+                $category->persist();
+            }
+            $this->data[] = $category->getName();
+            $this->categories[] = $category;
+        } elseif (isset($data['presets'])) {
             $presets = explode(',', $data['presets']);
             foreach ($presets as $preset) {
                 $category = $fixtureFactory->createByCode('catalogCategory', ['dataSet' => $preset]);
                 $category->persist();
 
                 /** @var CatalogCategory $category */
-                $this->data[] = [
-                    'id' => $category->getId(),
-                    'name' => $category->getName(),
-                ];
-                $this->category[] = $category;
+                $this->data[] = $category->getName();
+                $this->categories[] = $category;
             }
         }
     }
@@ -101,8 +98,8 @@ class CategoryIds implements FixtureInterface
     /**
      * Return prepared data set
      *
-     * @param $key [optional]
-     * @return mixed
+     * @param string|null $key
+     * @return array
      *
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
@@ -126,8 +123,23 @@ class CategoryIds implements FixtureInterface
      *
      * @return array
      */
-    public function getCategory()
+    public function getCategories()
     {
-        return $this->category;
+        return $this->categories;
+    }
+
+    /**
+     * Get id of categories
+     *
+     * @return array
+     */
+    public function getIds()
+    {
+        $ids = [];
+        foreach ($this->categories as $category) {
+            $ids[] = $category->getId();
+        }
+
+        return $ids;
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CheckoutData.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CheckoutData.php
new file mode 100644
index 0000000000000000000000000000000000000000..884b098f388339b01048445c9194face0437b60d
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CheckoutData.php
@@ -0,0 +1,103 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Fixture\CatalogProductSimple;
+
+use Mtf\Fixture\FixtureInterface;
+
+/**
+ * Class CheckoutData
+ * Data keys:
+ *  - preset (Checkout data verification preset name)
+ */
+class CheckoutData implements FixtureInterface
+{
+    /**
+     * Current preset
+     *
+     * @var string
+     */
+    protected $currentPreset;
+
+    /**
+     * @constructor
+     * @param array $params
+     * @param array $data
+     */
+    public function __construct(array $params, array $data = [])
+    {
+        $this->params = $params;
+        $this->data = (isset($data['value']) && $data['value'] != '-') ? $data['value'] : null;
+        if (isset($data['preset'])) {
+            $this->currentPreset = $data['preset'];
+        }
+    }
+
+    /**
+     * Persist custom selections products
+     *
+     * @return void
+     */
+    public function persist()
+    {
+        //
+    }
+
+    /**
+     * Return prepared data set
+     *
+     * @param int $key [optional]
+     * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function getData($key = null)
+    {
+        return $this->data;
+    }
+
+    /**
+     * Return data set configuration settings
+     *
+     * @return string
+     */
+    public function getDataConfig()
+    {
+        return $this->params;
+    }
+
+    /**
+     * Return array preset
+     *
+     * @return array|null
+     */
+    public function getPreset()
+    {
+        $presets = [];
+        if (!isset($presets[$this->currentPreset])) {
+            return null;
+        }
+        return $presets[$this->currentPreset];
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomOptions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomOptions.php
old mode 100644
new mode 100755
index b5b1a060b1b0ca866cba632dee4b166c4df91e39..ae564f6f61f72de0f354e040ae0cacdd01f91b5c
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomOptions.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomOptions.php
@@ -276,6 +276,150 @@ class CustomOptions implements FixtureInterface
                         ]
                     ]
                 ]
+            ],
+            'all_types' => [
+                [
+                    'title' => 'custom option field %isolation%',
+                    'type' => 'Field',
+                    'is_require' => 'Yes',
+                    'options' => [
+                        [
+                            'price' => 10,
+                            'price_type' => 'Fixed',
+                            'sku' => 'sku_field_option_%isolation%',
+                            'max_characters' => 1024
+                        ]
+                    ]
+                ],
+                [
+                    'title' => 'custom option Area %isolation%',
+                    'is_require' => 'Yes',
+                    'type' => 'Area',
+                    'options' => [
+                        [
+                            'price' => 10,
+                            'price_type' => 'Fixed',
+                            'sku' => 'sku_area_row_%isolation%',
+                            'max_characters' => '10'
+                        ]
+                    ]
+                ],
+                [
+                    'title' => 'custom option File %isolation%',
+                    'is_require' => 'No',
+                    'type' => 'File',
+                    'options' => [
+                        [
+                            'price' => 10,
+                            'price_type' => 'Fixed',
+                            'sku' => 'sku_file_row_%isolation%',
+                            'file_extension' => 'jpg',
+                            'image_size_x' => '100',
+                            'image_size_y' => '100'
+                        ]
+                    ]
+                ],
+                [
+                    'title' => 'custom option drop down %isolation%',
+                    'is_require' => 'Yes',
+                    'type' => 'Drop-down',
+                    'options' => [
+                        [
+                            'title' => '10 percent',
+                            'price' => 10,
+                            'price_type' => 'Percent',
+                            'sku' => 'sku_drop_down_row_1_%isolation%'
+                        ],
+                        [
+                            'title' => '20 percent',
+                            'price' => 20,
+                            'price_type' => 'Percent',
+                            'sku' => 'sku_drop_down_row_2_%isolation%'
+                        ],
+                        [
+                            'title' => '30 fixed',
+                            'price' => 30,
+                            'price_type' => 'Fixed',
+                            'sku' => 'sku_drop_down_row_3_%isolation%'
+                        ]
+                    ]
+                ],
+                [
+                    'title' => 'custom option Radio Buttons %isolation%',
+                    'is_require' => 'Yes',
+                    'type' => 'Radio Buttons',
+                    'options' => [
+                        [
+                            'title' => '20 percent',
+                            'price' => 20,
+                            'price_type' => 'Fixed',
+                            'sku' => 'sku_radio_buttons_row%isolation%'
+                        ]
+                    ]
+                ],
+                [
+                    'title' => 'custom option Checkbox %isolation%',
+                    'is_require' => 'Yes',
+                    'type' => 'Checkbox',
+                    'options' => [
+                        [
+                            'title' => '20 percent',
+                            'price' => 20,
+                            'price_type' => 'Fixed',
+                            'sku' => 'sku_checkbox_row%isolation%'
+                        ]
+                    ]
+                ],
+                [
+                    'title' => 'custom option Multiple Select %isolation%',
+                    'is_require' => 'Yes',
+                    'type' => 'Multiple Select',
+                    'options' => [
+                        [
+                            'title' => '20 percent',
+                            'price' => 20,
+                            'price_type' => 'Fixed',
+                            'sku' => 'sku_multiple_select_row%isolation%'
+                        ]
+                    ]
+                ],
+                [
+                    'title' => 'custom option Date %isolation%',
+                    'is_require' => 'Yes',
+                    'type' => 'Date',
+                    'options' => [
+                        [
+                            'price' => 20,
+                            'price_type' => 'Fixed',
+                            'sku' => 'sku_date_row%isolation%'
+                        ]
+                    ]
+                ],
+                [
+                    'title' => 'custom option Date & Time %isolation%',
+                    'is_require' => 'Yes',
+                    'type' => 'Date & Time',
+                    'options' => [
+                        [
+                            'price' => 20,
+                            'price_type' => 'Fixed',
+                            'sku' => 'sku_date_and_time_row%isolation%'
+                        ]
+                    ]
+                ],
+                [
+                    //TODO fixed setValue() for select type (contains => "=")
+                    'title' => 'custom option Time %isolation%',
+                    'is_require' => 'Yes',
+                    'type' => 'Date & Time',
+                    'options' => [
+                        [
+                            'price' => 20,
+                            'price_type' => 'Fixed',
+                            'sku' => 'sku_time_row%isolation%'
+                        ]
+                    ]
+                ]
             ]
         ];
         if (!isset($presets[$name])) {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/GroupPriceOptions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/GroupPriceOptions.php
index 361228f31e6bc2dd2cb7b9012e38667aa8408b53..f1c1639040e7bbe204dbec6badd47d0accf3b55d 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/GroupPriceOptions.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/GroupPriceOptions.php
@@ -33,7 +33,6 @@ use Mtf\Fixture\FixtureInterface;
  * Data keys:
  *  - preset (Price options preset name)
  *  - products (comma separated sku identifiers)
- *
  */
 class GroupPriceOptions implements FixtureInterface
 {
@@ -114,7 +113,7 @@ class GroupPriceOptions implements FixtureInterface
                     'website' => 'All Websites [USD]',
                     'customer_group' => 'NOT LOGGED IN'
                 ]
-            ]
+            ],
         ];
         if (!isset($presets[$name])) {
             return null;
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/Price.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/Price.php
index aef5c617c10f5c0e7ab967cb4a7ad37eb69c9237..7b9ddfe6c723fdb4ee72dd09f176173e14e112f2 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/Price.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/Price.php
@@ -36,6 +36,20 @@ use Mtf\Fixture\FixtureInterface;
  */
 class Price implements FixtureInterface
 {
+    /**
+     * Prepared dataSet data
+     *
+     * @var array
+     */
+    protected $data;
+
+    /**
+     * Data set configuration settings
+     *
+     * @var array
+     */
+    protected $params;
+
     /**
      * @var \Mtf\Fixture\FixtureFactory
      */
@@ -138,7 +152,7 @@ class Price implements FixtureInterface
                 'product_price' => '100.00',
                 'product_special_price' => '90.00',
                 'cart_price' => '90.00'
-            ]
+            ],
         ];
         if (!isset($presets[$this->currentPreset])) {
             return null;
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TierPriceOptions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TierPriceOptions.php
index f0e1d290c2e181b4a786170a06457ae42f107d7e..645eac17d343e6941792885a7eac5fe883f4836f 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TierPriceOptions.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TierPriceOptions.php
@@ -32,7 +32,6 @@ use Mtf\Fixture\FixtureInterface;
  * Data keys:
  *  - preset (Price options preset name)
  *  - products (comma separated sku identifiers)
- *
  */
 class TierPriceOptions implements FixtureInterface
 {
@@ -89,13 +88,13 @@ class TierPriceOptions implements FixtureInterface
     {
         $presets = [
             'default' => [
-                0 => [
-                    'price' => 150,
+                [
+                    'price' => 15,
                     'website' => 'All Websites [USD]',
                     'price_qty' => 3,
                     'customer_group' => 'ALL GROUPS'
                 ],
-                1 => [
+                [
                     'price' => 24,
                     'website' => 'All Websites [USD]',
                     'price_qty' => 15,
@@ -103,13 +102,13 @@ class TierPriceOptions implements FixtureInterface
                 ]
             ],
             'MAGETWO-23002' => [
-                0 => [
+                [
                     'price' => 90,
                     'website' => 'All Websites [USD]',
                     'price_qty' => 2,
                     'customer_group' => 'ALL GROUPS'
                 ]
-            ]
+            ],
         ];
 
         if (!isset($presets[$name])) {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.php
index 9022128f7bca18a2c81451c8549009a8ab7cb096..44b724c213585652e6bd59073c4e0dfb5674260d 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.php
@@ -120,6 +120,7 @@ class CatalogProductVirtual extends InjectableFixture
         'default_value' => '',
         'input' => 'text',
         'source' => 'Magento\Catalog\Test\Fixture\CatalogProductSimple\CategoryIds',
+        'group' => 'product-details',
     ];
 
     protected $color = [
@@ -579,7 +580,8 @@ class CatalogProductVirtual extends InjectableFixture
     protected $website_ids = [
         'attribute_code' => 'website_ids',
         'backend_type' => 'virtual',
-        'default_value' => 'Main Website',
+        'default_value' => ['Main Website'],
+        'group' => 'websites',
     ];
 
     public function getCategoryIds()
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.xml
index fee9f0037b27f1d9aa2e994fa81d94d76fb24238..37fb96f32497fba8bb270ecc678eb82123a00984 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.xml
@@ -38,6 +38,7 @@
             <default_value></default_value>
             <input>text</input>
             <fixture>Magento\Catalog\Test\Fixture\CatalogProductSimple\CategoryIds</fixture>
+            <group>product-details</group>
         </category_ids>
         <color>
             <attribute_code>color</attribute_code>
@@ -442,6 +443,12 @@
             <group>customer-options</group>
             <fixture>Magento\Catalog\Test\Fixture\CatalogProductSimple\CustomOptions</fixture>
         </custom_options>
+        <website_ids>
+            <attribute_code>website_ids</attribute_code>
+            <backend_type>virtual</backend_type>
+            <default_value>Main Website</default_value>
+            <group>websites</group>
+        </website_ids>
     </fields>
     <data_set>
         <sku></sku>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/ConfigurableProduct.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/ConfigurableProduct.php
index 7a0b52477633bf319c57d79d74c042c0e9ffeaea..344edc124ad91ff3ec4bad4064aac4edee0a1c79 100755
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/ConfigurableProduct.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/ConfigurableProduct.php
@@ -243,40 +243,40 @@ class ConfigurableProduct extends Product
                 ),
                 'configurable_attributes_data' => array(
                     'value' => array(
+                        '0' => array(
+                            'label' => array(
+                                'value' => '%attribute_label_1%'
+                            ),
                             '0' => array(
-                                'label' => array(
-                                    'value' => '%attribute_label_1%'
+                                'option_label' => array(
+                                    'value' => '%attribute_1_option_label_1%'
                                 ),
-                                '0' => array(
-                                    'option_label' => array(
-                                        'value' => '%attribute_1_option_label_1%'
-                                    ),
-                                    'pricing_value' => array(
-                                        'value' => '1'
-                                    ),
-                                    'is_percent' => array(
-                                        'value' => 'No'
-                                    ),
-                                    'include' => array(
-                                        'value' => 'Yes'
-                                    ),
+                                'pricing_value' => array(
+                                    'value' => '1'
+                                ),
+                                'is_percent' => array(
+                                    'value' => 'No'
+                                ),
+                                'include' => array(
+                                    'value' => 'Yes'
+                                ),
+                            ),
+                            '1' => array(
+                                'option_label' => array(
+                                    'value' => '%attribute_1_option_label_2%'
+                                ),
+                                'pricing_value' => array(
+                                    'value' => '2'
+                                ),
+                                'is_percent' => array(
+                                    'value' => 'No'
+                                ),
+                                'include' => array(
+                                    'value' => 'Yes'
                                 ),
-                                '1' => array(
-                                    'option_label' => array(
-                                        'value' => '%attribute_1_option_label_2%'
-                                    ),
-                                    'pricing_value' => array(
-                                        'value' => '2'
-                                    ),
-                                    'is_percent' => array(
-                                        'value' => 'No'
-                                    ),
-                                    'include' => array(
-                                        'value' => 'Yes'
-                                    ),
-                                )
                             )
-                        ),
+                        )
+                    ),
                     'group' => static::GROUP
                 ),
                 'variations-matrix' => array(
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogAttributeSet/Curl.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogAttributeSet/Curl.php
index dc4c1f9b6c37920e13267668ae468f7a9f6bcf87..86fa3f55a7f0cfc94c1f510e5a981dc5fffd18c0 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogAttributeSet/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogAttributeSet/Curl.php
@@ -30,6 +30,7 @@ use Mtf\Util\Protocol\CurlInterface;
 use Mtf\Util\Protocol\CurlTransport;
 use Mtf\Handler\Curl as AbstractCurl;
 use Mtf\Util\Protocol\CurlTransport\BackendDecorator;
+use Magento\Catalog\Test\Fixture\CatalogAttributeSet;
 
 /**
  * Class Curl
@@ -37,41 +38,175 @@ use Mtf\Util\Protocol\CurlTransport\BackendDecorator;
  */
 class Curl extends AbstractCurl implements CatalogAttributeSetInterface
 {
+    /**
+     * Regex for finding attribute set id
+     *
+     * @var string
+     */
+    protected $attributeSetId = '`http.*?product_set\/delete\/id\/(\d*?)\/`';
+
+    /**
+     * Regex for finding attributes
+     *
+     * @var string
+     */
+    protected $attributes = '#buildCategoryTree\(this.root,.*?(\[.*\}\]\}\])\);#s';
+
+    /**
+     * Regex for finding attribute set name
+     *
+     * @var string
+     */
+    protected $attributeSetName = '#id="attribute_set_name".*?value="([\w\d]+)"#s';
+
     /**
      * Post request for creating Attribute Set
      *
-     * @param FixtureInterface $fixture
+     * @param FixtureInterface|null $fixture
      * @return array
-     * @throws \Exception
+     *
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      */
     public function persist(FixtureInterface $fixture = null)
+    {
+        /** @var CatalogAttributeSet $fixture */
+        $response = $fixture->hasData('attribute_set_id')
+            ? $this->getDefaultAttributeSet($fixture)
+            : $this->createAttributeSet($fixture);
+
+        $attributeSetId = ($fixture->hasData('attribute_set_id'))
+            ? $fixture->getAttributeSetId()
+            : $this->getData($this->attributeSetId, $response);
+
+        $assignedAttributes = $fixture->hasData('assigned_attributes')
+            ? $fixture->getDataFieldConfig('assigned_attributes')['source']->getAttributes()
+            : [];
+        $dataAttribute = $this->getDataAttributes($response);
+
+        $lastAttribute = array_pop($dataAttribute['attributes']);
+
+        foreach ($assignedAttributes as $key => $assignedAttribute) {
+            $dataAttribute['attributes'][] = [
+                $assignedAttribute->getAttributeId(),
+                $dataAttribute['groups'][0][0],
+                ($lastAttribute[2] + ($key + 1)),
+                null,
+            ];
+        }
+
+        $this->updateAttributeSet($attributeSetId, $dataAttribute);
+
+        return ['attribute_set_id' => $attributeSetId];
+    }
+
+    /**
+     * Create Attribute Set
+     *
+     * @param CatalogAttributeSet $fixture
+     * @return string
+     */
+    protected function createAttributeSet(CatalogAttributeSet $fixture)
     {
         $data = $fixture->getData();
         if (!isset($data['gotoEdit'])) {
             $data['gotoEdit'] = 1;
         }
-        $data['skeleton_set'] = $fixture
-            ->getDataFieldConfig('skeleton_set')['source']
-            ->getAttributeSet()
+
+        $data['skeleton_set'] = $fixture->getDataFieldConfig('skeleton_set')['source']->getAttributeSet()
             ->getAttributeSetId();
 
         $url = $_ENV['app_backend_url'] . 'catalog/product_set/save/';
         $curl = new BackendDecorator(new CurlTransport(), new Config);
-        $curl->write(CurlInterface::POST, $url, '1.0', array(), $data);
+        $curl->addOption(CURLOPT_HEADER, 1);
+        $curl->write(CurlInterface::POST, $url, '1.0', [], $data);
+        $response = $curl->read();
+        $curl->close();
+
+        return $response;
+    }
+
+    /**
+     * Get Default Attribute Set page with curl
+     *
+     * @param CatalogAttributeSet $fixture
+     * @return string
+     */
+    protected function getDefaultAttributeSet(CatalogAttributeSet $fixture)
+    {
+        $url = $_ENV['app_backend_url'] . 'catalog/product_set/edit/id/' . $fixture->getAttributeSetId() . '/';
+        $curl = new BackendDecorator(new CurlTransport(), new Config);
+        $curl->write(CurlInterface::POST, $url, '1.0');
         $response = $curl->read();
         $curl->close();
 
-        preg_match(
-            '`http.*?id\/(\d*?)\/.*?data-ui-id=\"page-actions-toolbar-delete-button\".*`',
-            $response,
-            $matches
-        );
-        $id = isset($matches[1]) ? $matches[1] : null;
+        return $response;
+    }
+
+    /**
+     * Update Attribute Set
+     *
+     * @param int $attributeSetId
+     * @param array $dataAttribute
+     * @return void
+     */
+    protected function updateAttributeSet($attributeSetId, array $dataAttribute)
+    {
+        $data = ['data' => json_encode($dataAttribute)];
+        $url = $_ENV['app_backend_url'] . 'catalog/product_set/save/id/' . $attributeSetId . '/';
+        $curl = new BackendDecorator(new CurlTransport(), new Config);
+        $curl->write(CurlInterface::POST, $url, '1.0', [], $data);
+        $curl->read();
+        $curl->close();
+    }
 
-        if (!strpos($response, 'data-ui-id="messages-message-success"')) {
-            throw new \Exception("Attribute Set creating by curl handler was not successful!");
+    /**
+     * Get data attributes for curl
+     *
+     * @param string $response
+     * @return array
+     */
+    protected function getDataAttributes($response)
+    {
+        $attributes = $this->getData($this->attributes, $response, true);
+        $dataAttribute = [];
+
+        $index = 1;
+        foreach ($attributes as $key => $parentAttributes) {
+            $dataAttribute['groups'][$key][] = $parentAttributes['id'];
+            $dataAttribute['groups'][$key][] = $parentAttributes['text'];
+            $dataAttribute['groups'][$key][] = $key + 1;
+            foreach ($parentAttributes['children'] as $attribute) {
+                $dataAttribute['attributes'][$index][] = $attribute['id'];
+                $dataAttribute['attributes'][$index][] = $parentAttributes['id'];
+                $dataAttribute['attributes'][$index][] = $index;
+                $dataAttribute['attributes'][$index][] = $attribute['entity_id'];
+                $index++;
+            }
+        }
+        $dataAttribute['not_attributes'] = [];
+        $dataAttribute['removeGroups'] = [];
+        $dataAttribute['attribute_set_name'] = $this->getData($this->attributeSetName, $response);
+
+        return $dataAttribute;
+    }
+
+    /**
+     * Select data from response by regular expression
+     *
+     * @param string $regularExpression
+     * @param string $response
+     * @param bool $isJson
+     * @return mixed
+     * @throws \Exception
+     */
+    protected function getData($regularExpression, $response, $isJson = false)
+    {
+        preg_match($regularExpression, $response, $matches);
+        if (!isset($matches[1])) {
+            throw new \Exception("Can't find data in response by regular expression \"{$regularExpression}\".");
         }
 
-        return ['attribute_set_id' => $id];
+        return $isJson ? json_decode($matches[1], true) : $matches[1];
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogCategory/Curl.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogCategory/Curl.php
old mode 100644
new mode 100755
index 9333090e28c49a892154e5e0a6ec7aa089370b4f..7f3ec0347d1ba65fe32069b007677a0b32cde874
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogCategory/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogCategory/Curl.php
@@ -48,22 +48,38 @@ class Curl extends AbstractCurl implements CatalogCategoryInterface
         'filter_price_range',
     ];
 
+    /**
+     * Mapping values for data.
+     *
+     * @var array
+     */
+    protected $mappingData = [
+        'is_active' => [
+            'Yes' => 1,
+            'No' => 0,
+        ],
+        'include_in_menu' => [
+            'Yes' => 1,
+            'No' => 0,
+        ],
+        'display_mode' => [
+            'Static block and products' => 'PRODUCTS_AND_PAGE',
+            'Static block only' => 'PAGE',
+            'Products only' => 'PRODUCTS',
+        ],
+    ];
+
     /**
      * Post request for creating Subcategory
      *
-     * @param FixtureInterface $fixture [optional]
-     * @return mixed|string
+     * @param FixtureInterface|null $fixture [optional]
+     * @return array
      */
     public function persist(FixtureInterface $fixture = null)
     {
-        $data['general'] = $fixture->getData();
-        foreach ($data['general'] as $key => $value) {
-            if ($value == 'Yes') {
-                $data['general'][$key] = 1;
-            }
-            if ($value == 'No') {
-                $data['general'][$key] = 0;
-            }
+        $data['general'] = $this->replaceMappingData($fixture->getData());
+        if ($fixture->hasData('landing_page')) {
+            $data['general']['landing_page'] = $this->getBlockId($fixture->getLandingPage());
         }
 
         $diff = array_diff($this->dataUseConfig, array_keys($data['general']));
@@ -79,7 +95,27 @@ class Curl extends AbstractCurl implements CatalogCategoryInterface
         $curl->close();
 
         preg_match('#http://.+/id/(\d+).+store/#m', $response, $matches);
-        $id = isset($matches[1]) ? $matches[1] : null;
+        $id = isset($matches[1]) ? (int)$matches[1] : null;
+
         return ['id' => $id];
     }
+
+    /**
+     * Getting block id by name
+     *
+     * @param string $landingName
+     * @return int|null
+     */
+    public function getBlockId($landingName)
+    {
+        $url = $_ENV['app_backend_url'] . 'catalog/category';
+        $curl = new BackendDecorator(new CurlTransport(), new Config);
+        $curl->write(CurlInterface::POST, $url, '1.0', [], []);
+        $response = $curl->read();
+        $curl->close();
+        preg_match('~<option.*value="(\d+)".*>' . preg_quote($landingName) . '</option>~', $response, $matches);
+        $id = isset($matches[1]) ? (int)$matches[1] : null;
+
+        return $id;
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php
index 0c754bc08144e6e08a2317cf12ae8f9ab31077f5..f63463d550d29b3bb38d290fe3b75ccf24a4655f 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php
@@ -90,12 +90,32 @@ class Curl extends AbstractCurl implements CatalogProductSimpleInterface
         ]
     ];
 
+    /**
+     * Placeholder for price data sent Curl
+     *
+     * @var array
+     */
+    protected $priceData = [
+        'website' => [
+            'name' => 'website_id',
+            'data' => [
+                'All Websites [USD]' => 0
+            ]
+        ],
+        'customer_group' => [
+            'name' => 'cust_group',
+            'data' => [
+                'ALL GROUPS' => 32000,
+                'NOT LOGGED IN' => 0
+            ]
+        ]
+    ];
+
     /**
      * Post request for creating simple product
      *
      * @param FixtureInterface|null $fixture [optional]
      * @return array
-     * @throws \Exception
      *
      * @SuppressWarnings(PHPMD.NPathComplexity)
      * @SuppressWarnings(PHPMD.CyclomaticComplexity)
@@ -105,34 +125,9 @@ class Curl extends AbstractCurl implements CatalogProductSimpleInterface
         $config = $fixture->getDataConfig();
         $prefix = isset($config['input_prefix']) ? $config['input_prefix'] : null;
         $data = $this->prepareData($fixture, $prefix);
-
         return ['id' => $this->createProduct($data, $config)];
     }
 
-    /**
-     * Getting tax class id from tax rule page
-     *
-     * @param string $taxClassName
-     * @return int
-     * @throws \Exception
-     */
-    protected function getTaxClassId($taxClassName)
-    {
-        $url = $_ENV['app_backend_url'] . 'tax/rule/new/';
-        $curl = new BackendDecorator(new CurlTransport(), new Config);
-        $curl->addOption(CURLOPT_HEADER, 1);
-        $curl->write(CurlInterface::POST, $url, '1.0', array(), array());
-        $response = $curl->read();
-        $curl->close();
-
-        preg_match('~<option value="(\d+)".*>' . $taxClassName . '</option>~', $response, $matches);
-        if (!isset($matches[1]) || empty($matches[1])) {
-            throw new \Exception('Product tax class id ' . $taxClassName . ' undefined!');
-        }
-
-        return (int)$matches[1];
-    }
-
     /**
      * Prepare POST data for creating product request
      *
@@ -140,28 +135,34 @@ class Curl extends AbstractCurl implements CatalogProductSimpleInterface
      * @param string|null $prefix [optional]
      * @return array
      *
-     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      * @SuppressWarnings(PHPMD.NPathComplexity)
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      */
     protected function prepareData(FixtureInterface $fixture, $prefix = null)
     {
         $fields = $this->replaceMappingData($fixture->getData());
         // Getting Tax class id
         if ($fixture->hasData('tax_class_id')) {
-            $taxClassId = $fixture->getDataFieldConfig('tax_class_id')['source']->getTaxClass()->getId();
-            $fields['tax_class_id'] = ($taxClassId === null)
-                ? $this->getTaxClassId($fields['tax_class_id'])
-                : $taxClassId;
+            $fields['tax_class_id'] = $fixture->getDataFieldConfig('tax_class_id')['source']->getTaxClass()->getId();
         }
 
         if (!empty($fields['category_ids'])) {
             $categoryIds = [];
-            foreach ($fields['category_ids'] as $categoryData) {
-                $categoryIds[] = $categoryData['id'];
+            /** @var InjectableFixture $fixture */
+            foreach ($fixture->getDataFieldConfig('category_ids')['source']->getCategories() as $category) {
+                /** @var CatalogCategory $category */
+                $categoryIds[] = $category->getId();
             }
             $fields['category_ids'] = $categoryIds;
         }
-
+        
+        if (isset($fields['tier_price'])) {
+            $fields['tier_price'] = $this->preparePriceData($fields['tier_price']);
+        }
+        if (isset($fields['group_price'])) {
+            $fields['group_price'] = $this->preparePriceData($fields['group_price']);
+        }
+        
         if (!empty($fields['website_ids'])) {
             foreach ($fields['website_ids'] as &$value) {
                 $value = isset($this->mappingData['website_ids'][$value])
@@ -179,13 +180,11 @@ class Curl extends AbstractCurl implements CatalogProductSimpleInterface
             $fields['attribute_set_id'] = $attributeSetId;
         }
 
-        $fields = $this->prepareStockData($fields);
-
         return $prefix ? [$prefix => $fields] : $fields;
     }
 
     /**
-     * Preparation of stock data
+     * Preparation of tier price data
      *
      * @param array $fields
      * @return array
@@ -193,32 +192,16 @@ class Curl extends AbstractCurl implements CatalogProductSimpleInterface
      * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      * @SuppressWarnings(PHPMD.NPathComplexity)
      */
-    protected function prepareStockData(array $fields)
+    protected function preparePriceData(array $fields)
     {
-        if (isset($fields['quantity_and_stock_status']) && !is_array($fields['quantity_and_stock_status'])) {
-            $fields['quantity_and_stock_status'] = [
-                'qty' => $fields['qty'],
-                'is_in_stock' => $fields['quantity_and_stock_status']
-            ];
-        }
-
-        if (!isset($fields['stock_data']['is_in_stock'])) {
-            $fields['stock_data']['is_in_stock'] = isset($fields['quantity_and_stock_status']['is_in_stock'])
-                ? $fields['quantity_and_stock_status']['is_in_stock']
-                : (isset($fields['inventory_manage_stock']) ? $fields['inventory_manage_stock'] : null);
-        }
-        if (!isset($fields['stock_data']['qty'])) {
-            $fields['stock_data']['qty'] = isset($fields['quantity_and_stock_status']['qty'])
-                ? $fields['quantity_and_stock_status']['qty']
-                : null;
-        }
-
-        if (!isset($fields['stock_data']['manage_stock'])) {
-            $fields['stock_data']['manage_stock'] = (int)(!empty($fields['stock_data']['qty'])
-                || !empty($fields['stock_data']['is_in_stock']));
+        foreach ($fields as &$field) {
+            foreach ($this->priceData as $key => $data) {
+                $field[$data['name']] = $this->priceData[$key]['data'][$field[$key]];
+                unset($field[$key]);
+            }
+            $field['delete'] = '';
         }
-
-        return $this->filter($fields);
+        return $fields;
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductIndex.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductIndex.php
index 29af1a20c5f4972715005a39a750132988607e51..8913ed7440b8286a65940d57e5a1e89b85231b7d 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductIndex.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductIndex.php
@@ -47,9 +47,9 @@ class CatalogProductIndex extends BackendPage
             'locator' => '#messages',
             'strategy' => 'css selector',
         ],
-        'productBlock' => [
-            'name' => 'productBlock',
-            'class' => 'Magento\Catalog\Test\Block\Adminhtml\Product',
+        'gridPageActionBlock' => [
+            'name' => 'gridPageActionBlock',
+            'class' => 'Magento\Catalog\Test\Block\Adminhtml\Product\GridPageAction',
             'locator' => '#add_new_product',
             'strategy' => 'css selector',
         ],
@@ -59,12 +59,6 @@ class CatalogProductIndex extends BackendPage
             'locator' => '[id="page:main-container"]',
             'strategy' => 'css selector',
         ],
-        'FormPageActions' => [
-            'name' => 'GridPageActions',
-            'class' => 'Magento\Catalog\Test\Block\Adminhtml\Product\FormPageActions',
-            'locator' => '#add_new_product',
-            'strategy' => 'css selector',
-        ],
     ];
 
     /**
@@ -84,11 +78,11 @@ class CatalogProductIndex extends BackendPage
     }
 
     /**
-     * @return \Magento\Catalog\Test\Block\Adminhtml\Product
+     * @return \Magento\Catalog\Test\Block\Adminhtml\Product\GridPageAction
      */
-    public function getProductBlock()
+    public function getGridPageActionBlock()
     {
-        return $this->getBlockInstance('productBlock');
+        return $this->getBlockInstance('gridPageActionBlock');
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductIndex.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductIndex.xml
index 0f7cb2b405b8fe9e550032f7753a91d73be4b63f..86115986f042ac02bbcb09aee18151aa56bfa91f 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductIndex.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductIndex.xml
@@ -37,8 +37,8 @@
         <strategy>css selector</strategy>
     </block>
     <block>
-        <name>productBlock</name>
-        <class>Magento\Catalog\Test\Block\Adminhtml\Product</class>
+        <name>gridPageActionBlock</name>
+        <class>Magento\Catalog\Test\Block\Adminhtml\Product\GridPageAction</class>
         <locator>#add_new_product</locator>
         <strategy>css selector</strategy>
     </block>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductSetEdit.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductSetEdit.php
index 0b39dcd231e974ea6063aa9037d3937c42a2e536..cdcfaebf1a9023bc4f2767a0fea2650d2fc29016 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductSetEdit.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductSetEdit.php
@@ -47,6 +47,12 @@ class CatalogProductSetEdit extends BackendPage
             'locator' => '.attribute-set',
             'strategy' => 'css selector',
         ],
+        'attributeSetEditForm' => [
+            'name' => 'attributeSetEditForm',
+            'class' => 'Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\Set\Main\EditForm',
+            'locator' => '#set_name',
+            'strategy' => 'css selector',
+        ],
     ];
 
     /**
@@ -64,4 +70,11 @@ class CatalogProductSetEdit extends BackendPage
     {
         return $this->getBlockInstance('attributeSetEditBlock');
     }
+    /**
+     * @return \Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\Set\Main\EditForm
+     */
+    public function getAttributeSetEditForm()
+    {
+        return $this->getBlockInstance('attributeSetEditForm');
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductSetEdit.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductSetEdit.xml
index bcdc08250cf4055019f883a47117d1e2b3f2bfb0..e5e219884e5c4dd0415b6464437b9cbf294c84a3 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductSetEdit.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductSetEdit.xml
@@ -36,4 +36,10 @@
         <locator>#tree-div2</locator>
         <strategy>css selector</strategy>
     </block>
+    <block>
+        <name>attributeSetEditForm</name>
+        <class>Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\Set\Main\EditForm</class>
+        <locator>#set_name</locator>
+        <strategy>css selector</strategy>
+    </block>
 </page>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.php
index 72129db92426ac6c07975bf8ee24d9f04b288e48..75699ca9cc2bac42cd3c0385d8f91ebc090bea51 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.php
@@ -62,13 +62,13 @@ class CatalogCategoryView extends FrontendPage
         'titleBlock' => [
             'name' => 'titleBlock',
             'class' => 'Magento\Theme\Test\Block\Html\Title',
-            'locator' => '.page.title h1.title',
+            'locator' => '.page-title h1.title .base',
             'strategy' => 'css selector',
         ],
         'viewBlock' => [
             'name' => 'viewBlock',
             'class' => 'Magento\Catalog\Test\Block\Category\View',
-            'locator' => '.category.view',
+            'locator' => '.column.main',
             'strategy' => 'css selector',
         ],
     ];
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.xml
index 179054d44fc1f1f0aa573160650694de5a2be0bb..7f643881091d79c91626ab87bfd22f6ad7e5c91b 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryView.xml
@@ -51,13 +51,13 @@
     <block>
         <name>titleBlock</name>
         <class>Magento\Theme\Test\Block\Html\Title</class>
-        <locator>.page.title h1.title</locator>
+        <locator>.page-title h1.title .base</locator>
         <strategy>css selector</strategy>
     </block>
     <block>
         <name>viewBlock</name>
         <class>Magento\Catalog\Test\Block\Category\View</class>
-        <locator>.category.view</locator>
+        <locator>.column.main</locator>
         <strategy>css selector</strategy>
     </block>
 </page>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Product/CatalogProductCompare.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Product/CatalogProductCompare.php
new file mode 100644
index 0000000000000000000000000000000000000000..dd1b9857e6aedaa652f1b4fe7ca234f9eec363cf
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Product/CatalogProductCompare.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\Page\Product;
+
+use Mtf\Page\FrontendPage;
+
+/**
+ * Class CatalogProductCompare
+ * Frontend product compare page
+ */
+class CatalogProductCompare extends FrontendPage
+{
+    const MCA = 'catalog/product_compare/index';
+
+    protected $_blocks = [
+        'compareProductsBlock' => [
+            'name' => 'compareProductsBlock',
+            'class' => 'Magento\Catalog\Test\Block\Product\Compare\ListCompare',
+            'locator' => '.column.main',
+            'strategy' => 'css selector',
+        ],
+        'messagesBlock' => [
+            'name' => 'messagesBlock',
+            'class' => 'Magento\Core\Test\Block\Messages',
+            'locator' => '.page.messages .messages',
+            'strategy' => 'css selector',
+        ],
+    ];
+
+    /**
+     * Get compare products block
+     *
+     * @return \Magento\Catalog\Test\Block\Product\Compare\ListCompare
+     */
+    public function getCompareProductsBlock()
+    {
+        return $this->getBlockInstance('compareProductsBlock');
+    }
+
+    /**
+     * Get message block
+     *
+     * @return \Magento\Core\Test\Block\Messages
+     */
+    public function getMessagesBlock()
+    {
+        return $this->getBlockInstance('messagesBlock');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Product/CatalogProductCompare.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Product/CatalogProductCompare.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e1eec834eaacdad45f8e91d243091155bef2058a
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Product/CatalogProductCompare.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<page mca="catalog/product_compare/index" >
+    <block>
+        <name>compareProductsBlock</name>
+        <class>Magento\Catalog\Test\Block\Product\Compare\ListCompare</class>
+        <locator>.column.main</locator>
+        <strategy>css selector</strategy>
+    </block>
+    <block>
+        <name>messagesBlock</name>
+        <class>Magento\Core\Test\Block\Messages</class>
+        <locator>.page.messages .messages</locator>
+        <strategy>css selector</strategy>
+    </block>
+</page>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Product/CatalogProductView.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Product/CatalogProductView.php
index 8e0b3d43f38f94de3fb6b4c8347648fc5155a350..80446b453125edb32b8e9dccdb12184eb7a1a1c2 100755
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Product/CatalogProductView.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Product/CatalogProductView.php
@@ -79,7 +79,7 @@ class CatalogProductView extends FrontendPage
         'reviewSummary' => [
             'name' => 'reviewSummary',
             'class' => 'Magento\Review\Test\Block\Product\View\Summary',
-            'locator' => '.product.reviews.summary',
+            'locator' => '.product-reviews-summary',
             'strategy' => 'css selector',
         ],
         'reviewFormBlock' => [
@@ -103,7 +103,7 @@ class CatalogProductView extends FrontendPage
         'titleBlock' => [
             'name' => 'titleBlock',
             'class' => 'Magento\Theme\Test\Block\Html\Title',
-            'locator' => '.page.title',
+            'locator' => '.page-title h1.title .base',
             'strategy' => 'css selector',
         ]
     ];
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Product/CatalogProductView.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Product/CatalogProductView.xml
index e6301cff8ef22c11b40027dc40f3270fac1e79e7..79c874d2bc7b3beebac595a3526825c803232151 100755
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Product/CatalogProductView.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Product/CatalogProductView.xml
@@ -75,7 +75,7 @@
     <block>
         <name>reviewSummary</name>
         <class>Magento\Review\Test\Block\Product\View\Summary</class>
-        <locator>.product.reviews.summary</locator>
+        <locator>.product-reviews-summary</locator>
         <strategy>css selector</strategy>
     </block>
     <block>
@@ -93,7 +93,7 @@
     <block>
         <name>titleBlock</name>
         <class>Magento\Theme\Test\Block\Html\Title</class>
-        <locator>.page.title h1.title</locator>
+        <locator>.page-title h1.title .base</locator>
         <strategy>css selector</strategy>
     </block>
 </page>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogCategory.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogCategory.php
index 00e5f45899fa1940fbbf5adb30152e219a764537..2303a597c96929f7bdbe1865eb5442c3d237b1b5 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogCategory.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogCategory.php
@@ -33,6 +33,7 @@ use Mtf\Repository\AbstractRepository;
 class CatalogCategory extends AbstractRepository
 {
     /**
+     * @constructor
      * @param array $defaultConfig
      * @param array $defaultData
      *
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.php
old mode 100644
new mode 100755
index c908338c2edbe89daf7d33ec13a27f13795f63c3..8062fd7ff4b169640fa1d16b12f472c32d9ef777
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.php
@@ -55,6 +55,7 @@ class CatalogProductSimple extends AbstractRepository
             'price' => ['value' => 560.00, 'preset' => '-'],
             'tax_class_id' => ['dataSet' => 'Taxable Goods'],
             'website_ids' => ['Main Website'],
+            'visibility' => 'Catalog, Search',
         ];
 
         $this->_data['100_dollar_product'] = [
@@ -71,8 +72,8 @@ class CatalogProductSimple extends AbstractRepository
         ];
 
         $this->_data['40_dollar_product'] = [
-            'sku' => '40_dollar_product',
-            'name' => '40_dollar_product',
+            'sku' => '40_dollar_product%isolation%',
+            'name' => '40_dollar_product%isolation%',
             'type_id' => 'simple',
             'quantity_and_stock_status' => [
                 'qty' => 666.0000,
@@ -128,6 +129,28 @@ class CatalogProductSimple extends AbstractRepository
             'category_ids' => ['presets' => 'default_subcategory']
         ];
 
+        $this->_data['simple_for_composite_products'] = [
+            'name' => 'simple_for_composite_products%isolation%',
+            'sku' => 'simple_for_composite_products%isolation%',
+            'price' => ['value' => 560, 'preset' => '-'],
+            'attribute_set_id' => ['dataSet' => 'default'],
+            'tax_class_id' => ['dataSet' => 'Taxable Goods'],
+            'quantity_and_stock_status' => [
+                'qty' => 111,
+                'is_in_stock' => 'In Stock',
+            ],
+            'weight' => '1',
+            'status' => '1',
+            'website_ids' => ['Main Website'],
+            'stock_data' => [
+                'manage_stock' => 'Yes',
+                'qty' => '111',
+                'is_in_stock' => 'In Stock'
+            ],
+            'url_key' => 'simple-for-composite-products%isolation%',
+            'visibility' => 'Catalog, Search'
+        ];
+
         $this->_data['simple_for_salesrule_2'] = [
             'attribute_set_id' => ['dataSet' => 'default'],
             'name' => 'Simple Product %isolation%',
@@ -193,5 +216,35 @@ class CatalogProductSimple extends AbstractRepository
             'price' => ['value' => 100, 'preset' => '-'],
             'website_ids' => ['Main Website'],
         ];
+
+        $this->_data['withSpecialPrice'] = [
+            'type_id' => 'simple',
+            'attribute_set_id' => ['dataSet' => 'default'],
+            'name' => 'Simple Product %isolation%',
+            'sku' => 'sku_simple_product_%isolation%',
+            'price' => ['value' => 100, 'preset' => '-'],
+            'weight' => 1,
+            'special_price' => 9
+        ];
+
+        $this->_data['simple_with_group_price'] = [
+            'type_id' => 'simple',
+            'attribute_set_id' => ['dataSet' => 'default'],
+            'name' => 'Simple Product %isolation%',
+            'sku' => 'sku_simple_product_%isolation%',
+            'price' => ['value' => 100, 'preset' => '-'],
+            'weight' => 1,
+            'group_price' => ['preset' => 'default'],
+        ];
+
+        $this->_data['simple_with_tier_price'] = [
+            'type_id' => 'simple',
+            'attribute_set_id' => ['dataSet' => 'default'],
+            'name' => 'Simple Product %isolation%',
+            'sku' => 'sku_simple_product_%isolation%',
+            'price' => ['value' => 300, 'preset' => '-'],
+            'weight' => 1,
+            'tier_price' => ['preset' => 'default'],
+        ];
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.php
index db7579fae10b2944e74b8724c614d5faa37653f2..7c43610b0d73dd3e31e08a6c22128f98a3a62d4b 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.php
@@ -58,5 +58,22 @@ class CatalogProductVirtual extends AbstractRepository
             ],
             'price' => ['value' => 10.00, 'preset' => '-']
         ];
+
+        $this->_data['50_dollar_product'] = [
+            'name' => '50_dollar_product %isolation%',
+            'sku' => '50_dollar_product_%isolation%',
+            'tax_class_id' => ['dataSet' => 'Taxable Goods'],
+            'status' => 'Product online',
+            'website_ids' => ['Main Website'],
+            'is_virtual' => 'Yes',
+            'url_key' => 'virtual-product%isolation%',
+            'visibility' => 'Catalog, Search',
+            'attribute_set_id' => ['dataSet' => 'default'],
+            'quantity_and_stock_status' => [
+                'qty' => 111.0000,
+                'is_in_stock' => 'In Stock',
+            ],
+            'price' => ['value' => 50.00, 'preset' => '-']
+        ];
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/VirtualProduct.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/VirtualProduct.php
index ff5aafe8c101827226ffe75e233d21b4bffadfea..cd86c8a2069afffddf98677f7a28102b041d0cd2 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/VirtualProduct.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/VirtualProduct.php
@@ -24,6 +24,11 @@
 
 namespace Magento\Catalog\Test\Repository;
 
+/**
+ * Class VirtualProduct
+ * Virtual product repository
+ */
 class VirtualProduct extends Product
 {
+    //
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/AbstractCompareProductsTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/AbstractCompareProductsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4e2cb37e5b30d9bc8da6af78fe421e013c554d30
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/AbstractCompareProductsTest.php
@@ -0,0 +1,189 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\TestCase\Product;
+
+use Mtf\TestCase\Injectable;
+use Mtf\Fixture\FixtureFactory;
+use Mtf\Fixture\InjectableFixture;
+use Magento\Cms\Test\Page\CmsIndex;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Customer\Test\Page\CustomerAccountLogin;
+use Magento\Customer\Test\Fixture\CustomerInjectable;
+use Magento\Catalog\Test\Page\Product\CatalogProductView;
+use Magento\Catalog\Test\Page\Product\CatalogProductCompare;
+
+/**
+ * Class AbstractCompareProductsTest
+ * Abstract class for compare products class
+ */
+abstract class AbstractCompareProductsTest extends Injectable
+{
+    /**
+     * Array products
+     *
+     * @var array
+     */
+    protected $products;
+
+    /**
+     * Cms index page
+     *
+     * @var CmsIndex
+     */
+    protected $cmsIndex;
+
+    /**
+     * Catalog product compare page
+     *
+     * @var CatalogProductCompare
+     */
+    protected $catalogProductCompare;
+
+    /**
+     * Catalog product page
+     *
+     * @var CatalogProductView
+     */
+    protected $catalogProductView;
+
+    /**
+     * Customer login page
+     *
+     * @var CustomerAccountLogin
+     */
+    protected $customerAccountLogin;
+
+    /**
+     * Fixture factory
+     *
+     * @var FixtureFactory
+     */
+    protected $fixtureFactory;
+
+    /**
+     * Fixture customer
+     *
+     * @var CustomerInjectable
+     */
+    protected $customer;
+
+    /**
+     * Prepare data
+     *
+     * @param FixtureFactory $fixtureFactory
+     * @param CustomerInjectable $customer
+     * @return void
+     */
+    public function __prepare(FixtureFactory $fixtureFactory, CustomerInjectable $customer)
+    {
+        $this->fixtureFactory = $fixtureFactory;
+        $customer->persist();
+        $this->customer = $customer;
+    }
+
+    /**
+     * Injection data
+     *
+     * @param CmsIndex $cmsIndex
+     * @param CatalogProductView $catalogProductView
+     * @param CustomerAccountLogin $customerAccountLogin
+     * @return void
+     */
+    public function __inject(
+        CmsIndex $cmsIndex,
+        CatalogProductView $catalogProductView,
+        CustomerAccountLogin $customerAccountLogin
+    ) {
+        $this->cmsIndex = $cmsIndex;
+        $this->catalogProductView = $catalogProductView;
+        $this->customerAccountLogin = $customerAccountLogin;
+    }
+
+    /**
+     * Login customer
+     *
+     * @return void
+     */
+    protected function loginCustomer()
+    {
+        if (!$this->cmsIndex->getLinksBlock()->isLinkVisible('Log Out')) {
+            $this->cmsIndex->getLinksBlock()->openLink("Log In");
+            $this->customerAccountLogin->getLoginBlock()->login($this->customer);
+        }
+    }
+
+    /**
+     * Create products
+     *
+     * @param string $products
+     * @return array
+     */
+    protected function createProducts($products)
+    {
+        $products = explode(',', $products);
+        foreach ($products as $key => $product) {
+            list($fixture, $dataSet) = explode('::', $product);
+            $product = $this->fixtureFactory->createByCode($fixture, ['dataSet' => $dataSet]);
+            $product->persist();
+            $products[$key] = $product;
+        }
+        return $products;
+    }
+
+    /**
+     * Add products to compare list
+     *
+     * @param array $products
+     * @param AbstractConstraint $assert
+     * @return void
+     */
+    protected function addProducts(array $products, AbstractConstraint $assert = null)
+    {
+        foreach ($products as $itemProduct) {
+            $this->catalogProductView->init($itemProduct);
+            $this->catalogProductView->open();
+            $this->catalogProductView->getViewBlock()->clickAddToCompare();
+            if ($assert !== null) {
+                $this->productCompareAssert($assert, $itemProduct);
+            }
+        }
+    }
+
+    /**
+     * Perform assert
+     *
+     * @param AbstractConstraint $assert
+     * @param InjectableFixture $product
+     * @return void
+     */
+    protected function productCompareAssert(AbstractConstraint $assert, InjectableFixture $product)
+    {
+        $assert->configure(
+            $this,
+            ['catalogProductView' => $this->catalogProductView, 'product' => $product]
+        );
+        \PHPUnit_Framework_Assert::assertThat($this->getName(), $assert);
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/Configurable/CreateWithAttributeTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/Configurable/CreateWithAttributeTest.php
index cb6a5950987240c09af7d7f6d1491a0f6aa332a9..1e06b8d5b5f67ab7bad3d0c82b802d90a0c66fde 100755
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/Configurable/CreateWithAttributeTest.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/Configurable/CreateWithAttributeTest.php
@@ -91,7 +91,7 @@ class CreateWithAttributeTest extends Functional
 
         //Steps
         $manageProductsGrid->open();
-        $manageProductsGrid->getProductBlock()->addProduct();
+        $manageProductsGrid->getGridPageActionBlock()->addProduct();
         $productForm->fill($product);
         $productForm->openTab(Product::GROUP_PRODUCT_DETAILS);
         $productForm->addNewCategory($product);
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateConfigurableTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateConfigurableTest.php
index 6deb176332e5abac044ec1fb6ac78f2c2bd27709..1bc8c880df2a7aa09854bff0bd3cb54b69103238 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateConfigurableTest.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateConfigurableTest.php
@@ -60,7 +60,7 @@ class CreateConfigurableTest extends Functional
         $createProductPage = Factory::getPageFactory()->getCatalogProductNew();
         //Steps
         $manageProductsGrid->open();
-        $manageProductsGrid->getProductBlock()->addProduct('configurable');
+        $manageProductsGrid->getGridPageActionBlock()->addProduct('configurable');
         $productForm = $createProductPage->getProductForm();
         $productForm->fill($product);
         $createProductPage->getFormAction()->saveProduct($createProductPage, $product);
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateGroupedTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateGroupedTest.php
index 7ff383d0040103f81b63f395e3d6d8e59b00c297..668f68ed663598e8329aba985780146f39bc70de 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateGroupedTest.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateGroupedTest.php
@@ -62,7 +62,7 @@ class CreateGroupedTest extends Functional
         $productForm = $createProductPage->getProductForm();
         //Steps
         $manageProductsGrid->open();
-        $manageProductsGrid->getProductBlock()->addProduct('grouped');
+        $manageProductsGrid->getGridPageActionBlock()->addProduct('grouped');
         $productForm->fill($product);
         $createProductPage->getFormAction()->save();
         //Verifying
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.php
new file mode 100755
index 0000000000000000000000000000000000000000..5e9f56d36349a0e07b03852b8ee67d18cbed852a
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.php
@@ -0,0 +1,119 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\TestCase\Product;
+
+use Mtf\TestCase\Injectable;
+use Magento\Catalog\Test\Fixture\CatalogProductSimple;
+use Magento\Catalog\Test\Fixture\CatalogCategory;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+
+/**
+ * Test Creation for CreateSimpleProductEntity
+ *
+ * Test Flow:
+ * 1. Login to the backend.
+ * 2. Navigate to Products > Catalog.
+ * 3. Start to create simple product.
+ * 4. Fill in data according to data set.
+ * 5. Save Product.
+ * 6. Perform appropriate assertions.
+ *
+ * @group Products_(CS)
+ * @ZephyrId MAGETWO-23414
+ */
+class CreateSimpleProductEntityTest extends Injectable
+{
+    /**
+     * Category fixture
+     *
+     * @var CatalogCategory
+     */
+    protected $category;
+
+    /**
+     * Product page with a grid
+     *
+     * @var CatalogProductIndex
+     */
+    protected $productGrid;
+
+    /**
+     * Page to create a product
+     *
+     * @var CatalogProductNew
+     */
+    protected $newProductPage;
+
+    /**
+     * Prepare data
+     *
+     * @param CatalogCategory $category
+     * @return array
+     */
+    public function __prepare(CatalogCategory $category)
+    {
+        $category->persist();
+
+        return [
+            'category' => $category
+        ];
+    }
+
+    /**
+     * Injection data
+     *
+     * @param CatalogCategory $category
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductNew $newProductPage
+     * @return void
+     */
+    public function __inject(
+        CatalogCategory $category,
+        CatalogProductIndex $productGrid,
+        CatalogProductNew $newProductPage
+    ) {
+        $this->category = $category;
+        $this->productGrid = $productGrid;
+        $this->newProductPage = $newProductPage;
+    }
+
+    /**
+     * Run create product simple entity test
+     *
+     * @param CatalogProductSimple $product
+     * @param CatalogCategory $category
+     * @return void
+     */
+    public function testCreate(CatalogProductSimple $product, CatalogCategory $category)
+    {
+        // Steps
+        $this->productGrid->open();
+        $this->productGrid->getGridPageActionBlock()->addProduct('simple');
+        $productBlockForm = $this->newProductPage->getForm();
+        $productBlockForm->fill($product, null, $category);
+        $this->newProductPage->getFormAction()->save();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest/testCreate.csv b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest/testCreate.csv
new file mode 100644
index 0000000000000000000000000000000000000000..3fdd14092f40ecdac812115e979275b306efd906
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest/testCreate.csv
@@ -0,0 +1,19 @@
+"product/data/name";"product/data/sku";"product/data/tax_class_id/dataSet";"product/data/price/value";"product/data/special_price";"product/data/short_description";"product/data/description";"product/data/weight";"product/data/quantity_and_stock_status/qty";"product/data/quantity_and_stock_status/is_in_stock";"product/data/visibility";"constraint";"product/data/custom_options/preset";"product/data/price/preset";"product/data/group_price/preset";"product/data/tier_price/preset"
+"Simple Product %isolation%";"simple_sku_%isolation%";"-";"10000";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"50";"657";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertProductInCategory, assertProductPage, assertProductInCart";"MAGETWO-23062";"MAGETWO-23062";"-";"-"
+"Simple Product %isolation%";"simple_sku_%isolation%";"-";"10001";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"51";"658";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertProductInCategory, assertProductPage, assertProductInCart";"MAGETWO-23063";"MAGETWO-23063";"-";"-"
+"Simple Product %isolation%";"simple_sku_%isolation%";"-";"10002";"90";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"52";"659";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertProductInCategory, assertProductPage, assertProductInCart";"MAGETWO-23062";"MAGETWO-23029";"-";"-"
+"Simple Product %isolation%";"simple_sku_%isolation%";"-";"10003";"90";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"53";"660";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertProductInCategory, assertProductPage, assertProductInCart";"MAGETWO-23063";"MAGETWO-23030";"-";"-"
+"Simple Product %isolation%";"simple_sku_%isolation%";"-";"10004";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"54";"661";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertProductInCategory, assertProductPage, assertProductInCart";"MAGETWO-23063";"MAGETWO-23030";"MAGETWO-23055";"-"
+"Simple Product %isolation%";"simple_sku_%isolation%";"-";"10005";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"55";"662";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertProductInCategory, assertProductPage, assertProductInCart";"MAGETWO-23062";"MAGETWO-23029";"MAGETWO-23055";"-"
+"Simple Product %isolation%";"simple_sku_%isolation%";"-";"10006";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"56";"663";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertProductInCategory, assertProductPage, assertProductInCart";"MAGETWO-23063";"MAGETWO-23030";"-";"MAGETWO-23002"
+"Simple Product %isolation%";"simple_sku_%isolation%";"-";"10007";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"57";"664";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertProductInCategory, assertProductPage, assertProductInCart";"MAGETWO-23062";"MAGETWO-23029";"-";"MAGETWO-23002"
+"Simple Product %isolation%";"simple_sku_%isolation%";"-";"10008";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"58";"665";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertProductVisibleInCategory, assertProductPage";"-";"-";"-";"-"
+"Simple Product %isolation%";"simple_sku_%isolation%";"-";"10009";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"59";"75";"In Stock";"-";"assertProductSaveMessage, assertProductInStock";"-";"-";"-";"-"
+"Simple Product %isolation%";"simple_sku_%isolation%";"-";"10010";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"60";"0";"Out of Stock";"-";"assertProductSaveMessage, assertProductOutOfStock";"-";"-";"-";"-"
+"Simple Product %isolation%";"simple_sku_%isolation%";"-";"10011";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"61";"138";"-";"Search";"assertProductSaveMessage, assertProductSearchableBySku";"-";"-";"-";"-"
+"Simple Product %isolation%";"simple_sku_%isolation%";"-";"10012";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"62";"139";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductInStock, assertProductSearchableBySku, assertProductPage";"-";"-";"-";"-"
+"Simple Product %isolation%";"simple_sku_%isolation%";"-";"10013";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"63";"140";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductInStock, assertProductVisibleInCategory, assertProductPage";"-";"-";"-";"-"
+"Simple Product %isolation%";"simple_sku_%isolation%";"Taxable Goods";"10014";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"64";"141";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductInStock, assertProductVisibleInCategory, assertProductPage, assertProductGroupedPriceOnProductPage";"-";"-";"default";"-"
+"Simple Product %isolation%";"simple_sku_%isolation%";"Taxable Goods";"10015";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"65";"142";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductInStock, assertProductVisibleInCategory, assertProductPage, assertProductSpecialPriceOnProductPage";"-";"-";"-";"-"
+"Simple Product %isolation%";"simple_sku_%isolation%";"None";"10016";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"66";"143";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductInStock, assertProductVisibleInCategory, assertProductPage, assertProductTierPriceOnProductPage";"-";"-";"-";"default"
+"Simple Product %isolation%";"simple_sku_%isolation%";"-";"10017";"-";"Simple Product short_description %isolation%";"Simple Product description %isolation%";"67";"144";"-";"-";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductInStock, assertProductVisibleInCategory, assertProductPage, assertProductCustomOptionsOnProductPage";"options-suite";"-";"-";"-"
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleWithCategoryTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleWithCategoryTest.php
index 4a4e413458ce8915ef6f2b2a988f8fb5896458f6..6b011703794e1f68ced48372dc5b8ea28dc1ec6d 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleWithCategoryTest.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleWithCategoryTest.php
@@ -59,7 +59,7 @@ class CreateSimpleWithCategoryTest extends Functional
         //Page & Blocks
         $productListPage = Factory::getPageFactory()->getCatalogProductIndex();
         $createProductPage = Factory::getPageFactory()->getCatalogProductNew();
-        $addProductBlock = $productListPage->getProductBlock();
+        $addProductBlock = $productListPage->getGridPageActionBlock();
         $productForm = $createProductPage->getProductForm();
 
         //Steps
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleWithCustomOptionsAndCategoryTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleWithCustomOptionsAndCategoryTest.php
old mode 100644
new mode 100755
index 3226fb642ccf2b7c0a13f88bee295fe6a38157b7..272ec07ac31176cae095c06fd4105f3332f790f3
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleWithCustomOptionsAndCategoryTest.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleWithCustomOptionsAndCategoryTest.php
@@ -60,7 +60,8 @@ class CreateSimpleWithCustomOptionsAndCategoryTest extends Functional
         $productForm = $createProductPage->getForm();
         //Steps
         $createProductPage->open();
-        $productForm->fillProduct($product);
+        $category = $product->getCategories()['category'];
+        $productForm->fill($product, null, $category);
         $createProductPage->getFormAction()->save();
         //Verifying
         $createProductPage->getMessagesBlock()->assertSuccessMessage();
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateVirtualProductEntityTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateVirtualProductEntityTest.php
old mode 100644
new mode 100755
index 939f39a411a85d840f43393c1a2453235ee94085..74c3de8495496efa10b70991194314a3be334aeb
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateVirtualProductEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateVirtualProductEntityTest.php
@@ -105,9 +105,9 @@ class CreateVirtualProductEntityTest extends Injectable
     {
         // Steps
         $this->productGrid->open();
-        $this->productGrid->getProductBlock()->addProduct('virtual');
+        $this->productGrid->getGridPageActionBlock()->addProduct('virtual');
         $productBlockForm = $this->newProductPage->getForm();
-        $productBlockForm->fillProduct($product, $category);
+        $productBlockForm->fill($product, null, $category);
         $this->newProductPage->getFormAction()->save();
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateVirtualProductEntityTest/testCreate.csv b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateVirtualProductEntityTest/testCreate.csv
index de3705644ba17a842ade495d66b0c068da297133..204ed2c43a4a96f7b539b4b0f2bce8248a26626c 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateVirtualProductEntityTest/testCreate.csv
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateVirtualProductEntityTest/testCreate.csv
@@ -3,6 +3,6 @@
 "VirtualProduct %isolation%";"virtual_sku_%isolation%";"10";"None";"999";"Yes";"category_%isolation%";"-";"-";"MAGETWO-23002";"Yes";"In Stock";"-";"Catalog, Search";"assertProductSaveMessage, assertProductVisibleInCategory, assertProductForm, assertProductSearchableBySku"
 "VirtualProduct %isolation%";"-";"10";"Taxable Goods";"999";"Yes";"-";"-";"MAGETWO-23030";"-";"-";"Out of Stock";"-";"Search";"assertProductSaveMessage, assertProductForm, assertProductSkuAutoGenerated, assertProductSearchableBySku"
 "VirtualProduct %isolation%";"virtual_sku_%isolation%";"10";"-";"-";"Yes";"category_%isolation%";"MAGETWO-23055";"-";"-";"-";"-";"-";"Catalog";"assertProductSaveMessage, assertProductForm, assertProductVisibleInCategory"
-"VirtualProduct %isolation%";"virtual_sku_%isolation%";"9000";"-";"-";"Yes";"-";"MAGETWO-23055";"-";"-";"-";"-";"options-suite";"-";"assertProductSaveMessage, assertProductSearchableBySku, assertProductPage, assertGroupedPriceOnProductPage, assertCustomOptionsOnProductPage"
-"VirtualProduct %isolation%";"virtual_sku_%isolation%";"10";"-";"999";"Yes";"-";"-";"MAGETWO-23030";"-";"No";"In Stock";"-";"-";"assertProductSaveMessage, assertProductPage, assertSpecialPriceOnProductPage, assertProductInStock"
-"VirtualProduct %isolation%";"virtual_sku_%isolation%";"9000";"-";"999";"Yes";"-";"-";"-";"default";"-";"Out of Stock";"-";"-";"assertProductSaveMessage, assertProductPage, assertTierPriceOnProductPage, assertProductOutOfStock"
+"VirtualProduct %isolation%";"virtual_sku_%isolation%";"9000";"-";"-";"Yes";"-";"MAGETWO-23055";"-";"-";"-";"-";"options-suite";"-";"assertProductSaveMessage, assertProductSearchableBySku, assertProductPage, assertProductGroupedPriceOnProductPage, assertProductCustomOptionsOnProductPage"
+"VirtualProduct %isolation%";"virtual_sku_%isolation%";"10";"-";"999";"Yes";"-";"-";"MAGETWO-23030";"-";"No";"In Stock";"-";"-";"assertProductSaveMessage, assertProductPage, assertProductSpecialPriceOnProductPage, assertProductInStock"
+"VirtualProduct %isolation%";"virtual_sku_%isolation%";"9000";"-";"999";"Yes";"-";"-";"-";"default";"-";"Out of Stock";"-";"-";"assertProductSaveMessage, assertProductPage, assertProductTierPriceOnProductPage, assertProductOutOfStock"
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.php
old mode 100644
new mode 100755
index 2b63d75ec3f356b175970f155dcb2d4d9169fcb3..2bf01a6dd0ec276adc58d0326695ba986199cd30
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateSimpleProductEntityTest.php
@@ -95,7 +95,7 @@ class UpdateSimpleProductEntityTest extends Injectable
      * @param CatalogProductEdit $editProductPage
      * @param CatalogCategory $category
      * @param FixtureFactory $fixtureFactory
-     * @return array
+     * @return void
      */
     public function __inject(
         CatalogProductIndex $productGrid,
@@ -131,7 +131,7 @@ class UpdateSimpleProductEntityTest extends Injectable
         $filter = ['sku' => $this->product->getSku()];
         $this->productGrid->open()->getProductGrid()->searchAndOpen($filter);
         $productBlockForm = $this->editProductPage->getForm();
-        $productBlockForm->fillProduct($product);
+        $productBlockForm->fill($product);
         $this->editProductPage->getFormAction()->save();
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateVirtualProductEntityTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateVirtualProductEntityTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1d3781e35c6d6800bbe96bdad3bff939ef76acec
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateVirtualProductEntityTest.php
@@ -0,0 +1,137 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\TestCase\Product;
+
+use Mtf\TestCase\Injectable;
+use Mtf\Fixture\FixtureFactory;
+use Magento\Catalog\Test\Fixture\CatalogCategory;
+use Magento\Catalog\Test\Fixture\CatalogProductVirtual;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+
+/**
+ * Test Creation for UpdateVirtualProductEntity
+ *
+ * Test Flow:
+ *
+ * Precondition:
+ * 1. Category is created.
+ * 2. Virtual product is created and assigned to created category.
+ *
+ * Steps:
+ * 1. Login to backend.
+ * 2. Navigate to PRODUCTS -> Catalog.
+ * 3. Select a product in the grid.
+ * 4. Edit test value(s) according to dataset.
+ * 5. Click "Save".
+ * 6. Perform asserts.
+ *
+ * @group Products_(CS)
+ * @ZephyrId MAGETWO-26204
+ */
+class UpdateVirtualProductEntityTest extends Injectable
+{
+    /**
+     * Virtual product fixture
+     *
+     * @var CatalogProductVirtual
+     */
+    protected $product;
+
+    /**
+     * Product page with a grid
+     *
+     * @var CatalogProductIndex
+     */
+    protected $productGrid;
+
+    /**
+     * Page to update a product
+     *
+     * @var CatalogProductEdit
+     */
+    protected $editProductPage;
+
+    /**
+     * Prepare data
+     *
+     * @param CatalogCategory $category
+     * @return array
+     */
+    public function __prepare(CatalogCategory $category)
+    {
+        $category->persist();
+        return [
+            'category' => $category
+        ];
+    }
+
+    /**
+     * Injection data
+     *
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductEdit $editProductPage
+     * @param CatalogCategory $category
+     * @param FixtureFactory $fixtureFactory
+     * @return void
+     */
+    public function __inject(
+        CatalogProductIndex $productGrid,
+        CatalogProductEdit $editProductPage,
+        CatalogCategory $category,
+        FixtureFactory $fixtureFactory
+    ) {
+        $this->product = $fixtureFactory->createByCode(
+            'catalogProductVirtual',
+            [
+                'dataSet' => 'default',
+                'data' => [
+                    'category_ids' => [
+                        'category' => $category
+                    ]
+                ]
+            ]
+        );
+        $this->product->persist();
+
+        $this->productGrid = $productGrid;
+        $this->editProductPage = $editProductPage;
+    }
+
+    /**
+     * Run update product virtual entity test
+     *
+     * @param CatalogProductVirtual $product
+     * @return void
+     */
+    public function test(CatalogProductVirtual $product)
+    {
+        // Steps
+        $this->productGrid->open();
+        $this->productGrid->getProductGrid()->searchAndOpen(['sku' => $this->product->getSku()]);
+        $this->editProductPage->getForm()->fill($product);
+        $this->editProductPage->getFormAction()->save();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateVirtualProductEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateVirtualProductEntityTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..8c4e634beabb14bdab9c845d812aad6d944e8a24
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/UpdateVirtualProductEntityTest/test.csv
@@ -0,0 +1,12 @@
+"product/data/name";"product/data/sku";"product/data/price/value";"product/data/tax_class_id/dataSet";"product/data/quantity_and_stock_status/qty";"product/data/is_virtual";"product/data/category_ids/presets";"product/data/group_price/preset";"product/data/special_price";"product/data/tier_price/preset";"product/data/quantity_and_stock_status/is_in_stock";"product/data/custom_options/preset";"product/data/visibility";"constraint"
+"VirtualProduct %isolation%";"virtual_sku_%isolation%";"99.99";"None";"999";"Yes";"default_subcategory";"-";"-";"MAGETWO-23002";"In Stock";"-";"Catalog";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductPage, assertProductVisibleInCategory, assertProductInCategory, assertProductTierPriceOnProductPage, assertProductSearchableBySku "
+"virtual_product_%isolation%";"virtual_sku_%isolation%";"120.00";"Taxable Goods";"999";"Yes";"-";"-";"45";"-";"In Stock";"-";"Catalog, Search";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductPage, assertProductVisibleInCategory, assertProductInCategory, assertProductPage, assertProductSpecialPriceOnProductPage, assertProductSearchableBySku"
+"VirtualProduct %isolation%";"virtual_sku_%isolation%";"185.00";"None";"999";"Yes";"default_subcategory";"-";"-";"MAGETWO-23002";"Out of Stock";"-";"Catalog, Search";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductPage, assertProductVisibleInCategory, assertProductPage, assertProductOutOfStock, assertProductTierPriceOnProductPage, assertProductSearchableBySku"
+"virtual_product_%isolation%";"virtual_sku_%isolation%";"99.99";"Taxable Goods";"-";"Yes";"-";"-";"-";"-";"Out of Stock";"-";"Search";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductPage, assertProductOutOfStock, assertProductSearchableBySku"
+"VirtualProduct %isolation%";"virtual_sku_%isolation%";"5.00";"None";"-";"Yes";"-";"-";"-";"-";"Out of Stock";"-";"Catalog";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductPage, assertProductOutOfStock, assertProductSearchableBySku"
+"virtual_product_%isolation%";"virtual_sku_%isolation%";"145.00";"Taxable Goods";"999";"Yes";"default_subcategory";"MAGETWO-23055";"-";"MAGETWO-23002";"In Stock";"-";"Catalog, Search";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductPage, assertProductVisibleInCategory, assertProductGroupedPriceOnProductPage, assertProductTierPriceOnProductPage, assertProductSearchableBySku"
+"VirtualProduct %isolation%";"virtual_sku_%isolation%";"99.99";"None";"-";"Yes";"default_subcategory";"-";"45";"-";"Out of Stock";"-";"Catalog, Search";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductPage, assertProductOutOfStock, assertProductSearchableBySku"
+"virtual_product_%isolation%";"virtual_sku_%isolation%";"5.00";"Taxable Goods";"-";"Yes";"-";"MAGETWO-23055";"-";"-";"Out of Stock";"-";"Search";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductPage, assertProductOutOfStock,  assertProductSearchableBySku"
+"VirtualProduct %isolation%";"virtual_sku_%isolation%";"120.00";"None";"999";"Yes";"default_subcategory";"-";"-";"-";"In Stock";"options-suite";"Search";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductPage, assertProductSpecialPriceOnProductPage, assertProductCustomOptionsOnProductPage, assertProductSearchableBySku"
+"VirtualProduct %isolation%";"virtual_sku_%isolation%";"99.99";"Taxable Goods";"-";"Yes";"-";"MAGETWO-23055";"-";"-";"Out of Stock";"-";"Catalog, Search";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductPage, assertProductOutOfStock, assertProductSearchableBySku"
+"VirtualProduct %isolation%";"virtual_sku_%isolation%";"99.99";"None";"999";"Yes";"default_subcategory";"MAGETWO-23055";"-";"MAGETWO-23002";"In Stock";"-";"Catalog";"assertProductSaveMessage, assertProductInGrid, assertProductForm, assertProductPage, assertProductVisibleInCategory, assertProductSpecialPriceOnProductPage, assertProductPage, assertProductGroupedPriceOnProductPage, assertProductTierPriceOnProductPage, assertProductInCategory, assertProductSearchableBySku"
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest/testCreateProductAttribute.csv b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest/testCreateProductAttribute.csv
old mode 100644
new mode 100755
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAssignedToTemplateProductAttributeTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAssignedToTemplateProductAttributeTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7d47022330a61f4502840a637f827d5f29ab5738
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAssignedToTemplateProductAttributeTest.php
@@ -0,0 +1,105 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\TestCase\ProductAttribute;
+
+use Mtf\TestCase\Injectable;
+use Magento\Catalog\Test\Fixture\CatalogAttributeSet;
+use Magento\Catalog\Test\Fixture\CatalogProductAttribute;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductAttributeIndex;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductAttributeNew;
+
+/**
+ * Test Creation for Delete Attribute Set (Product Template)
+ *
+ * Preconditions:
+ * 1. Create Product template, based on Default
+ * 2. Create product attribute and add to created template
+ *
+ * Test Flow:
+ * 1. Log in to Backend.
+ * 2. Go to Stores > Attributes > Product
+ * 3. Search product attribute in grid by given data
+ * 4. Open this attribute by clicking
+ * 5. Click on the "Delete Attribute" button
+ * 6. Perform all assertions.
+ *
+ * @group Product_Attributes_(MX)
+ * @ZephyrId MAGETWO-26011
+ */
+class DeleteAssignedToTemplateProductAttributeTest extends Injectable
+{
+    /**
+     * Catalog Product Attribute index page
+     *
+     * @var CatalogProductAttributeIndex
+     */
+    protected $attributeIndex;
+
+    /**
+     * Catalog Product Attribute new page
+     *
+     * @var CatalogProductAttributeNew
+     */
+    protected $attributeNew;
+
+    /**
+     * Inject pages
+     *
+     * @param CatalogProductAttributeIndex $attributeIndex
+     * @param CatalogProductAttributeNew $attributeNew
+     * @return void
+     */
+    public function __inject(CatalogProductAttributeIndex $attributeIndex, CatalogProductAttributeNew $attributeNew)
+    {
+        $this->attributeIndex = $attributeIndex;
+        $this->attributeNew = $attributeNew;
+    }
+
+    /**
+     * Run DeleteAssignedToTemplateProductAttribute test
+     *
+     * @param CatalogAttributeSet $productTemplate
+     * @return array
+     */
+    public function test(CatalogAttributeSet $productTemplate)
+    {
+        // Precondition
+        $productTemplate->persist();
+
+        // Steps
+        $filter = [
+            'attribute_code' => $productTemplate
+                ->getDataFieldConfig('assigned_attributes')['source']
+                ->getAttributes()[0]
+                ->getAttributeCode()
+        ];
+
+        $this->attributeIndex->open();
+        $this->attributeIndex->getGrid()->searchAndOpen($filter);
+        $this->attributeNew->getPageActions()->delete();
+
+        return ['productTemplate' => $productTemplate];
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAssignedToTemplateProductAttributeTest/test.csv b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAssignedToTemplateProductAttributeTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..8633f468c2410d59e05fbbbef1c2adf6b8c26289
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAssignedToTemplateProductAttributeTest/test.csv
@@ -0,0 +1,3 @@
+"productTemplate/dataSet";"productTemplate/data/assigned_attributes/presets";"constraint"
+"custom_attribute_set";"attribute_type_dropdown";"assertProductAttributeSuccessDeleteMessage, assertProductAttributeAbsenceInGrid, assertProductAttributeAbsenceForAttributeMapping, assertProductAttributeAbsenceInTemplateGroups, assertProductAttributeAbsenceInUnassignedAttributes"
+"default";"attribute_type_text_field";"assertProductAttributeSuccessDeleteMessage, assertProductAttributeAbsenceInGrid, assertProductAttributeAbsenceInVariationsSearch"
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAttributeSetTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAttributeSetTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..cf7ae657609bb3554648cf470c4ccabfe2600d30
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAttributeSetTest.php
@@ -0,0 +1,112 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\TestCase\ProductAttribute;
+
+use Mtf\Fixture\FixtureFactory;
+use Mtf\TestCase\Injectable;
+use Magento\Catalog\Test\Fixture\CatalogAttributeSet;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex;
+
+/**
+ * Test Creation for Delete Attribute Set (Product Template)
+ *
+ * Preconditions:
+ * 1. An attribute is created.
+ * 2. An attribute template is created.
+ * 3. A simple product is created with this attribute and template
+ *
+ * Test Flow:
+ * 1. Log in to Backend.
+ * 2. Navigate to Stores > Attributes > Product Template.
+ * 3. Open created Product Template.
+ * 4. Click 'Delete Attribute Set' button.
+ * 5. Perform all assertions.
+ *
+ * @group Product_Attributes_(MX)
+ * @ZephyrId MAGETWO-25473
+ */
+class DeleteAttributeSetTest extends Injectable
+{
+    /**
+     * Catalog Product Set index page
+     *
+     * @var CatalogProductSetIndex
+     */
+    protected $productSetIndex;
+
+    /**
+     * Catalog Product Set edit page
+     *
+     * @var CatalogProductSetEdit
+     */
+    protected $productSetEdit;
+
+    /**
+     * Inject data
+     *
+     * @param CatalogProductSetIndex $productSetIndex
+     * @param CatalogProductSetEdit $productSetEdit
+     * @return void
+     */
+    public function __inject(
+        CatalogProductSetIndex $productSetIndex,
+        CatalogProductSetEdit $productSetEdit
+    ) {
+        $this->productSetIndex = $productSetIndex;
+        $this->productSetEdit = $productSetEdit;
+    }
+
+    /**
+     * Run DeleteAttributeSet test
+     *
+     * @param FixtureFactory $fixtureFactory
+     * @param CatalogAttributeSet $productTemplate
+     * @return array
+     */
+    public function test(FixtureFactory $fixtureFactory, CatalogAttributeSet $productTemplate)
+    {
+        // Precondition
+        $productTemplate->persist();
+        $product = $fixtureFactory->createByCode(
+            'catalogProductSimple',
+            [
+                'dataSet' => 'default',
+                'data' => [
+                    'attribute_set_id' => ['attribute_set' => $productTemplate],
+                ],
+            ]
+        );
+        $product->persist();
+
+        // Steps
+        $filter = ['set_name' => $productTemplate->getAttributeSetName()];
+        $this->productSetIndex->open();
+        $this->productSetIndex->getGrid()->searchAndOpen($filter);
+        $this->productSetEdit->getPageActions()->delete();
+
+        return ['product' => $product];
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAttributeSetTest/test.csv b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAttributeSetTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..362d06693eaeb77517b2197d03d233746fa5d2e6
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAttributeSetTest/test.csv
@@ -0,0 +1,2 @@
+"productTemplate/dataSet";"productTemplate/data/assigned_attributes/presets";"product/dataSet";"constraint"
+"custom_attribute_set";"default";"default";"assertProductTemplateSuccessDeleteMessage, assertProductTemplateNotInGrid, assertProductNotInGrid"
\ No newline at end of file
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..cd73dba5a491894f38974fec7a79aba61795107d
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Test\TestCase\ProductAttribute;
+
+use Mtf\TestCase\Injectable;
+use Magento\Catalog\Test\Fixture\CatalogAttributeSet;
+use Magento\Catalog\Test\Fixture\CatalogProductAttribute;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex;
+
+/**
+ * Test Creation for UpdateAttributeSetTest
+ *
+ * Preconditions:
+ * 1. An attribute is created
+ * 2. An attribute template is created
+ *
+ * Test Flow:
+ * 1. Log in to Backend.
+ * 2. Navigate to Stores > Attributes > Product Template.
+ * 3. Open created Product Template.
+ * 4. Click 'Add New' button to create new group
+ * 5. Add created Product Attribute to created group.
+ * 6. Fill out other fields data according to data set.
+ * 7. Save Product Template.
+ * 8. Preform all assertions.
+ *
+ * @group Product_Attributes_(CS)
+ * @ZephyrId MAGETWO-26251
+ */
+class UpdateAttributeSetTest extends Injectable
+{
+    /**
+     * Catalog Product Set page
+     *
+     * @var CatalogProductSetIndex
+     */
+    protected $productSetIndex;
+
+    /**
+     * Catalog Product Set edit page
+     *
+     * @var CatalogProductSetEdit
+     */
+    protected $productSetEdit;
+
+    /**
+     * Inject data
+     *
+     * @param CatalogProductSetIndex $productSetIndex
+     * @param CatalogProductSetEdit $productSetEdit
+     * @return void
+     */
+    public function __inject(
+        CatalogProductSetIndex $productSetIndex,
+        CatalogProductSetEdit $productSetEdit
+    ) {
+        $this->productSetIndex = $productSetIndex;
+        $this->productSetEdit = $productSetEdit;
+    }
+
+    /**
+     * Run UpdateProductTemplate test
+     *
+     * @param CatalogAttributeSet $attributeSet
+     * @param CatalogAttributeSet $attributeSetOriginal
+     * @param CatalogProductAttribute $productAttributeOriginal
+     * @return void
+     */
+    public function test(
+        CatalogAttributeSet $attributeSet,
+        CatalogAttributeSet $attributeSetOriginal,
+        CatalogProductAttribute $productAttributeOriginal
+    ) {
+        // Precondition
+        $attributeSetOriginal->persist();
+        $productAttributeOriginal->persist();
+        // Steps
+        $filter = ['set_name' => $attributeSetOriginal->getAttributeSetName()];
+        $this->productSetIndex->open();
+        $this->productSetIndex->getGrid()->searchAndOpen($filter);
+        $groupName = $attributeSet->getGroup();
+        $this->productSetEdit->getAttributeSetEditBlock()->addAttributeSetGroup($groupName);
+        $this->productSetEdit->getAttributeSetEditBlock()
+            ->moveAttribute($productAttributeOriginal->getData(), $groupName);
+        $this->productSetEdit->getAttributeSetEditForm()->fill($attributeSet);
+        $this->productSetEdit->getPageActions()->save();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest/test.csv b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..c7edd39778f676936296aebf77b2f0e27069f087
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest/test.csv
@@ -0,0 +1,2 @@
+"attributeSet/data/attribute_set_name";"attributeSet/data/group";"attributeSetOriginal/dataSet";"productAttributeOriginal/dataSet";"constraint"
+"ProductTemplateEdit1%isolation%";"Custom-group%isolation%";"custom_attribute_set";"attribute_type_text_field";"assertProductTemplateSuccessSaveMessage, assertProductTemplateForm, assertProductTemplateInGrid, assertProductTemplateOnProductForm, assertProductTemplateGroupOnProductForm"
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/global/constraint.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/global/constraint.xml
old mode 100644
new mode 100755
index e3c25a122c8d7b76398b5f690509065a17a70239..f4694337a906207d69b6a175435dd881e57c0f36
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/global/constraint.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/global/constraint.xml
@@ -27,104 +27,113 @@
     <assertProductInGrid module="Magento_Catalog">
         <severeness>high</severeness>
         <require>
-            <productGrid class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
+            <productGrid class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex" />
+            <product class="Mtf\Fixture\FixtureInterface" />
         </require>
     </assertProductInGrid>
     <assertProductSaveMessage module="Magento_Catalog">
         <severeness>low</severeness>
         <require>
-            <productPage class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit"/>
+            <productPage class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit" />
         </require>
     </assertProductSaveMessage>
     <assertProductOutOfStock module="Magento_Catalog">
         <severeness>low</severeness>
         <require>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
+            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
+            <product class="Mtf\Fixture\FixtureInterface" />
         </require>
     </assertProductOutOfStock>
     <assertProductInStock module="Magento_Catalog">
         <severeness>low</severeness>
         <require>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
+            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
+            <product class="Mtf\Fixture\FixtureInterface" />
         </require>
     </assertProductInStock>
     <assertProductVisibleInCategory module="Magento_Catalog">
         <severeness>low</severeness>
         <require>
-            <catalogCategoryView class="Magento\Catalog\Test\Page\Category\CatalogCategoryView"/>
-            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex"/>
-            <category class="Magento\Catalog\Test\Fixture\CatalogCategory"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
+            <catalogCategoryView class="Magento\Catalog\Test\Page\Category\CatalogCategoryView" />
+            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex" />
+            <category class="Magento\Catalog\Test\Fixture\CatalogCategory" />
+            <product class="Mtf\Fixture\FixtureInterface" />
         </require>
     </assertProductVisibleInCategory>
+    <assertProductNotVisibleInCategory module="Magento_Catalog">
+        <severeness>low</severeness>
+        <require>
+            <catalogCategoryView class="Magento\Catalog\Test\Page\Category\CatalogCategoryView" />
+            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex" />
+            <category class="Magento\Catalog\Test\Fixture\CatalogCategory" />
+            <product class="Mtf\Fixture\FixtureInterface" />
+        </require>
+    </assertProductNotVisibleInCategory>
     <assertProductSearchableBySku module="Magento_Catalog">
         <severeness>low</severeness>
         <require>
-            <catalogSearchResult class="Magento\CatalogSearch\Test\Page\CatalogsearchResult"/>
-            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
+            <catalogSearchResult class="Magento\CatalogSearch\Test\Page\CatalogsearchResult" />
+            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex" />
+            <product class="Mtf\Fixture\FixtureInterface" />
         </require>
     </assertProductSearchableBySku>
     <assertProductInCategory module="Magento_Catalog">
         <severeness>low</severeness>
         <require>
-            <catalogCategoryView class="Magento\Catalog\Test\Page\Category\CatalogCategoryView"/>
-            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
-            <category class="Magento\Catalog\Test\Fixture\CatalogCategory"/>
+            <catalogCategoryView class="Magento\Catalog\Test\Page\Category\CatalogCategoryView" />
+            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex" />
+            <product class="Mtf\Fixture\FixtureInterface" />
+            <category class="Magento\Catalog\Test\Fixture\CatalogCategory" />
         </require>
     </assertProductInCategory>
     <assertProductInCart module="Magento_Catalog">
         <severeness>low</severeness>
         <require>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
-            <checkoutCart class="Magento\Checkout\Test\Page\CheckoutCart"/>
+            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
+            <product class="Mtf\Fixture\FixtureInterface" />
+            <checkoutCart class="Magento\Checkout\Test\Page\CheckoutCart" />
         </require>
     </assertProductInCart>
     <assertProductPage module="Magento_Catalog">
         <severeness>low</severeness>
         <require>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
+            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
+            <product class="Mtf\Fixture\FixtureInterface" />
         </require>
     </assertProductPage>
-    <assertGroupedPriceOnProductPage module="Magento_Catalog">
+    <assertProductGroupedPriceOnProductPage module="Magento_Catalog">
         <severeness>low</severeness>
         <require>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
+            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
+            <product class="Mtf\Fixture\FixtureInterface" />
         </require>
-    </assertGroupedPriceOnProductPage>
-    <assertSpecialPriceOnProductPage module="Magento_Catalog">
+    </assertProductGroupedPriceOnProductPage>
+    <assertProductSpecialPriceOnProductPage module="Magento_Catalog">
         <severeness>low</severeness>
         <require>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
+            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
+            <product class="Mtf\Fixture\FixtureInterface" />
         </require>
-    </assertSpecialPriceOnProductPage>
-    <assertTierPriceOnProductPage module="Magento_Catalog">
+    </assertProductSpecialPriceOnProductPage>
+    <assertProductTierPriceOnProductPage module="Magento_Catalog">
         <severeness>low</severeness>
         <require>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
+            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
+            <product class="Mtf\Fixture\FixtureInterface" />
         </require>
-    </assertTierPriceOnProductPage>
-    <assertCustomOptionsOnProductPage module="Magento_Catalog">
+    </assertProductTierPriceOnProductPage>
+    <assertProductCustomOptionsOnProductPage module="Magento_Catalog">
         <severeness>low</severeness>
         <require>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
+            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
+            <product class="Mtf\Fixture\FixtureInterface" />
         </require>
-    </assertCustomOptionsOnProductPage>
+    </assertProductCustomOptionsOnProductPage>
     <assertProductForm module="Magento_Catalog">
         <severeness>low</severeness>
         <require>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
+            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
+            <product class="Mtf\Fixture\FixtureInterface" />
         </require>
     </assertProductForm>
     <assertAddToCartButtonAbsent module="Magento_Catalog">
@@ -136,32 +145,32 @@
     <assertProductIsNotDisplayingOnFrontend module="Magento_Catalog">
         <severeness>high</severeness>
         <require>
-            <catalogCategoryView class="Magento\Catalog\Test\Page\Category\CatalogCategoryView"/>
-            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
-            <category class="Magento\Catalog\Test\Fixture\CatalogCategory"/>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView"/>
-            <catalogSearchResult class="Magento\CatalogSearch\Test\Page\CatalogsearchResult"/>
+            <catalogCategoryView class="Magento\Catalog\Test\Page\Category\CatalogCategoryView" />
+            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex" />
+            <product class="Mtf\Fixture\FixtureInterface" />
+            <category class="Magento\Catalog\Test\Fixture\CatalogCategory" />
+            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
+            <catalogSearchResult class="Magento\CatalogSearch\Test\Page\CatalogsearchResult" />
         </require>
     </assertProductIsNotDisplayingOnFrontend>
     <assertProductSkuAutoGenerated module="Magento_Catalog">
         <severeness>low</severeness>
         <require>
-            <productGrid class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
+            <productGrid class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex" />
+            <product class="Mtf\Fixture\FixtureInterface" />
         </require>
     </assertProductSkuAutoGenerated>
-    <assertGroupedPriceOnProductPage module="Magento_Catalog">
+    <assertProductGroupedPriceOnProductPage module="Magento_Catalog">
         <severeness>low</severeness>
         <require>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView"/>
-            <product class="Mtf\Fixture\FixtureInterface"/>
+            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView"  />
+            <product class="Mtf\Fixture\FixtureInterface" />
         </require>
-    </assertGroupedPriceOnProductPage>
+    </assertProductGroupedPriceOnProductPage>
     <assertProductAttributeSaveMessage module="Magento_Catalog">
         <severeness>high</severeness>
         <require>
-            <attributeIndex class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductAttributeIndex"/>
+            <attributeIndex class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductAttributeIndex" />
         </require>
     </assertProductAttributeSaveMessage>
     <assertProductAttributeInGrid module="Magento_Catalog">
@@ -225,12 +234,12 @@
     <assertCrossSellsProductsSection module="Magento_Catalog">
         <severeness>middle</severeness>
         <require>
-            <product1 class="Magento\Catalog\Test\Fixture\CatalogProductSimple"/>
-            <product2 class="Magento\Catalog\Test\Fixture\CatalogProductSimple"/>
-            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex"/>
-            <catalogCategoryView class="Magento\Catalog\Test\Page\Category\CatalogCategoryView"/>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView"/>
-            <checkoutCart class="Magento\Checkout\Test\Page\CheckoutCart"/>
+            <product1 class="Magento\Catalog\Test\Fixture\CatalogProductSimple" />
+            <product2 class="Magento\Catalog\Test\Fixture\CatalogProductSimple" />
+            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex" />
+            <catalogCategoryView class="Magento\Catalog\Test\Page\Category\CatalogCategoryView" />
+            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
+            <checkoutCart class="Magento\Checkout\Test\Page\CheckoutCart" />
         </require>
     </assertCrossSellsProductsSection>
     <assertProductAttributeSuccessDeleteMessage module="Magento_Catalog">
@@ -242,11 +251,11 @@
     <assertRelatedProductsSection module="Magento_Catalog">
         <severeness>middle</severeness>
         <require>
-            <product1 class="Magento\Catalog\Test\Fixture\CatalogProductSimple"/>
-            <product2 class="Magento\Catalog\Test\Fixture\CatalogProductSimple"/>
-            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex"/>
-            <catalogCategoryView class="Magento\Catalog\Test\Page\Category\CatalogCategoryView"/>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView"/>
+            <product1 class="Magento\Catalog\Test\Fixture\CatalogProductSimple" />
+            <product2 class="Magento\Catalog\Test\Fixture\CatalogProductSimple" />
+            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex" />
+            <catalogCategoryView class="Magento\Catalog\Test\Page\Category\CatalogCategoryView" />
+            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
         </require>
     </assertRelatedProductsSection>
     <assertProductAttributeAbsenceInGrid module="Magento_Catalog">
@@ -258,11 +267,11 @@
     <assertUpSellsProductsSection module="Magento_Catalog">
         <severeness>middle</severeness>
         <require>
-            <product1 class="Magento\Catalog\Test\Fixture\CatalogProductSimple"/>
-            <product2 class="Magento\Catalog\Test\Fixture\CatalogProductSimple"/>
-            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex"/>
-            <catalogCategoryView class="Magento\Catalog\Test\Page\Category\CatalogCategoryView"/>
-            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView"/>
+            <product1 class="Magento\Catalog\Test\Fixture\CatalogProductSimple" />
+            <product2 class="Magento\Catalog\Test\Fixture\CatalogProductSimple" />
+            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex" />
+            <catalogCategoryView class="Magento\Catalog\Test\Page\Category\CatalogCategoryView" />
+            <catalogProductView class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
         </require>
     </assertUpSellsProductsSection>
     <assertProductAttributeAbsenceInSearchOnProductForm module="Magento_Catalog">
@@ -312,33 +321,41 @@
     </assertCategoryAbsenceOnBackend>
     <assertProductTemplateSuccessSaveMessage module="Magento_Catalog">
         <severeness>high</severeness>
-        <productSetIndex class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex" />
+        <require>
+            <productSetIndex class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex" />
+        </require>
     </assertProductTemplateSuccessSaveMessage>
     <assertProductTemplateForm module="Magento_Catalog">
         <severeness>high</severeness>
-        <productSet class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex" />
-        <productSetEdit class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetEdit" />
-        <attributeSet class="Magento\Catalog\Test\Fixture\CatalogAttributeSet" />
-        <productAttribute class="Magento\Catalog\Test\Fixture\CatalogProductAttribute" />
+        <require>
+            <productSet class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex" />
+            <productSetEdit class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetEdit" />
+            <attributeSet class="Magento\Catalog\Test\Fixture\CatalogAttributeSet" />
+            <productAttribute class="Magento\Catalog\Test\Fixture\CatalogProductAttribute" />
+        </require>
     </assertProductTemplateForm>
     <assertProductTemplateInGrid module="Magento_Catalog">
         <severeness>high</severeness>
-        <productSet class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex" />
-        <attributeSet class="Magento\Catalog\Test\Fixture\CatalogAttributeSet" />
+        <require>
+            <productSet class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex" />
+            <attributeSet class="Magento\Catalog\Test\Fixture\CatalogAttributeSet" />
+        </require>
     </assertProductTemplateInGrid>
     <assertProductTemplateOnProductForm module="Magento_Catalog">
         <severeness>high</severeness>
-        <fixtureFactory class="Mtf\Fixture\FixtureFactory" />
-        <attributeSet class="Magento\Catalog\Test\Fixture\CatalogAttributeSet" />
-        <productEdit class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit" />
-        <productGrid class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex" />
-        <newProductPage class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew" />
-        <productAttribute class="Magento\Catalog\Test\Fixture\CatalogProductAttribute" />
+        <require>
+            <fixtureFactory class="Mtf\Fixture\FixtureFactory" />
+            <attributeSet class="Magento\Catalog\Test\Fixture\CatalogAttributeSet" />
+            <productEdit class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit" />
+            <productGrid class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex" />
+            <newProductPage class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew" />
+            <productAttribute class="Magento\Catalog\Test\Fixture\CatalogProductAttribute" />
+        </require>
     </assertProductTemplateOnProductForm>
     <assertAbsenceDeleteAttributeButton module="Magento_Catalog">
         <severeness>high</severeness>
         <require>
-            <attributeNew class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductAttributeNew"/>
+            <attributeNew class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductAttributeNew" />
         </require>
     </assertAbsenceDeleteAttributeButton>
     <assertProductSuccessDeleteMessage module="Magento_Catalog">
@@ -347,4 +364,95 @@
     <assertProductNotInGrid module="Magento_Catalog">
         <severeness>low</severeness>
     </assertProductNotInGrid>
+    <assertProductTemplateSuccessDeleteMessage module="Magento_Catalog">
+        <severeness>high</severeness>
+    </assertProductTemplateSuccessDeleteMessage>
+    <assertProductTemplateNotInGrid module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductTemplateNotInGrid>
+    <assertProductNotInGrid module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductNotInGrid>
+    <assertProductNotSearchableBySku module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductNotSearchableBySku>
+    <assertProductCompareItemsLink module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductCompareItemsLink>
+    <assertProductComparePage module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductComparePage>
+    <assertProductCompareBlockOnCmsPage module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductCompareBlockOnCmsPage>
+    <assertProductCompareSuccessAddMessage module="Magento_Catalog">
+        <severeness>high</severeness>
+    </assertProductCompareSuccessAddMessage>
+    <assertProductCompareSuccessRemoveMessage module="Magento_Catalog">
+        <severeness>high</severeness>
+    </assertProductCompareSuccessRemoveMessage>
+    <assertProductCompareSuccessRemoveAllProductsMessage module="Magento_Catalog">
+        <severeness>high</severeness>
+    </assertProductCompareSuccessRemoveAllProductsMessage>
+    <assertProductCompareItemsLinkIsAbsent module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductCompareItemsLinkIsAbsent>
+    <assertProductCompareRemoveLastProductMessage module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductCompareRemoveLastProductMessage>
+    <assertProductIsNotVisibleInCompareBlock module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductIsNotVisibleInCompareBlock>
+    <assertProductCompareSuccessRemoveMessage module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductCompareSuccessRemoveMessage>
+    <assertProductIsNotVisibleInComparePage module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductIsNotVisibleInComparePage>
+    <assertProductAttributeAbsenceInTemplateGroups module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductAttributeAbsenceInTemplateGroups>
+    <assertProductAttributeAbsenceInUnassignedAttributes module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductAttributeAbsenceInUnassignedAttributes>
+    <assertProductAttributeAbsenceInVariationsSearch module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductAttributeAbsenceInVariationsSearch>
+    <assertProductDuplicateMessage module="Magento_Catalog">
+        <severeness>high</severeness>
+        <require>
+            <productPage class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit" />
+        </require>
+    </assertProductDuplicateMessage>
+    <assertProductDuplicatedInGrid module="Magento_Catalog">
+        <severeness>low</severeness>
+        <require>
+            <product class="Mtf\Fixture\FixtureInterface" />
+            <productGrid class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex" />
+        </require>
+    </assertProductDuplicatedInGrid>
+    <assertProductDuplicateIsNotDisplayingOnFrontend module="Magento_Catalog">
+        <severeness>high</severeness>
+    </assertProductDuplicateIsNotDisplayingOnFrontend>
+    <assertProductDuplicateForm module="Magento_Catalog">
+        <severeness>high</severeness>
+    </assertProductDuplicateForm>
+    <assertProductForm module="Magento_Catalog">
+        <severeness>high</severeness>
+    </assertProductForm>
+    <assertProductTemplateGroupOnProductForm module="Magento_Catalog">
+        <severeness>high</severeness>
+    </assertProductTemplateGroupOnProductForm>
+    <assertProductCompareSuccessRemoveAllProductsMessage module="Magento_Catalog">
+        <severeness>high</severeness>
+    </assertProductCompareSuccessRemoveAllProductsMessage>
+    <assertProductCompareItemsLinkIsAbsent module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductCompareItemsLinkIsAbsent>
+    <assertProductCompareRemoveLastProductMessage module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductCompareRemoveLastProductMessage>
+    <assertProductIsNotVisibleInCompareBlock module="Magento_Catalog">
+        <severeness>low</severeness>
+    </assertProductIsNotVisibleInCompareBlock>
 </constraint>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/global/fixture.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/global/fixture.xml
index e9a13691255236a1840bdf51410a1cf23b3e581b..5a98b6e360203f9043e20308a8d3158c8afd922c 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/global/fixture.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/global/fixture.xml
@@ -216,5 +216,15 @@
         <type>flat</type>
         <entity_type>eav_attribute_set</entity_type>
         <collection>Magento\Catalog\Model\Resource\Product\Link\Product\Collection</collection>
+        <fields>
+            <skeleton_set>
+                <attribute_code>skeleton_set</attribute_code>
+                <backend_type>virtual</backend_type>
+            </skeleton_set>
+            <assigned_attributes>
+                <attribute_code>assigned_attributes</attribute_code>
+                <backend_type>virtual</backend_type>
+            </assigned_attributes>
+        </fields>
     </catalogAttributeSet>
 </fixture>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/global/page.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/global/page.xml
index 5fd15786ae5d72f18767ea11a426f6e065a1f0cc..41de6c334f1105ad9160b617827fcf08144cce83 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/global/page.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/global/page.xml
@@ -84,4 +84,9 @@
         <area>adminhtml</area>
         <class>Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetAdd</class>
     </catalogProductSetAdd>
+    <catalogProductCompare>
+        <mca>catalog/product_compare/index</mca>
+        <area>product</area>
+        <class>Magento\Catalog\Test\Page\Product\CatalogProductCompare</class>
+    </catalogProductCompare>
 </page>
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Adminhtml/Edit/SearchTermForm.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Adminhtml/Edit/SearchTermForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..8a4d0067e358f3c12fc3fe1f40c231fddba45f57
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Adminhtml/Edit/SearchTermForm.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\CatalogSearch\Test\Block\Adminhtml\Edit;
+
+use Magento\Backend\Test\Block\Widget\Form as WidgetForm;
+
+/**
+ * Class Form
+ * Form for search term
+ */
+class SearchTermForm extends WidgetForm
+{
+    //
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Adminhtml/Edit/SearchTermForm.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Adminhtml/Edit/SearchTermForm.xml
new file mode 100644
index 0000000000000000000000000000000000000000..69a93cd6406d90d8c22f4e408f19d3123ddaf5d7
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Adminhtml/Edit/SearchTermForm.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <query_text />
+        <store_id>
+            <input>selectstore</input>
+        </store_id>
+        <num_results />
+        <popularity />
+        <synonym_for />
+        <redirect />
+        <display_in_terms>
+            <input>select</input>
+        </display_in_terms>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Adminhtml/Grid.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Adminhtml/Grid.php
new file mode 100644
index 0000000000000000000000000000000000000000..f81b4f5ac9734ddd6ad12ed2d3b091ee7dcdcef6
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Block/Adminhtml/Grid.php
@@ -0,0 +1,65 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\CatalogSearch\Test\Block\Adminhtml;
+
+use Magento\Backend\Test\Block\Widget\Grid as WidgetGrid;
+
+/**
+ * Class Grid
+ * Backend search terms grid
+ */
+class Grid extends WidgetGrid
+{
+    /**
+     * Initialize block elements
+     *
+     * @var array
+     */
+    protected $filters = [
+        'search_query' => [
+            'selector' => 'input[name="search_query"]'
+        ],
+        'store_id' => [
+            'selector' => 'select[name="store_id"]',
+            'input' => 'selectstore'
+        ],
+        'results_from' => [
+            'selector' => 'input[name="num_results[from]"]'
+        ],
+        'popularity_from' => [
+            'selector' => 'input[name="popularity[from]"]'
+        ],
+        'synonym_for' => [
+            'selector' => 'input[name="synonym_for"]'
+        ],
+        'redirect' => [
+            'selector' => 'input[name="redirect"]'
+        ],
+        'display_in_terms' => [
+            'selector' => 'select[name="display_in_terms"]',
+            'input' => 'select'
+        ]
+    ];
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermForm.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..6fdc76c4e09de8db6f6ca3a441fb3e32b89fdcab
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermForm.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\CatalogSearch\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery;
+use Magento\CatalogSearch\Test\Page\Adminhtml\CatalogSearchEdit;
+use Magento\CatalogSearch\Test\Page\Adminhtml\CatalogSearchIndex;
+
+/**
+ * Class AssertSearchTermForm
+ * Assert that after save a search term on edit term search page displays
+ */
+class AssertSearchTermForm extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'high';
+
+    /**
+     * Assert that after save a search term on edit term search page displays:
+     *  - correct Search Query field passed from fixture
+     *  - correct Store
+     *  - correct Number of results
+     *  - correct Number of Uses
+     *  - correct Synonym For
+     *  - correct Redirect URL
+     *  - correct Display in Suggested Terms
+     *
+     * @param CatalogSearchIndex $indexPage
+     * @param CatalogSearchEdit $editPage
+     * @param CatalogSearchQuery $searchTerm
+     * @return void
+     */
+    public function processAssert(
+        CatalogSearchIndex $indexPage,
+        CatalogSearchEdit $editPage,
+        CatalogSearchQuery $searchTerm
+    ) {
+        $indexPage->open()->getGrid()->searchAndOpen(['search_query' => $searchTerm->getQueryText()]);
+        $formData = $editPage->getForm()->getData($searchTerm);
+        $fixtureData = $searchTerm->getData();
+
+        \PHPUnit_Framework_Assert::assertEquals(
+            $formData,
+            $fixtureData,
+            'This form "Search Term" does not match the fixture data.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'These form "Search Term" correspond to the fixture data.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermInGrid.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermInGrid.php
new file mode 100644
index 0000000000000000000000000000000000000000..51950166cb8e3bb982a46c328ddf0134adf10875
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermInGrid.php
@@ -0,0 +1,88 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\CatalogSearch\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery;
+use Magento\CatalogSearch\Test\Page\Adminhtml\CatalogSearchIndex;
+
+/**
+ * Class AssertSearchTermInGrid
+ * Assert that after save a term search on edit term search page displays
+ */
+class AssertSearchTermInGrid extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'high';
+
+    /**
+     * Assert that after save a term search on edit term search page displays:
+     *  - correct Search Query field passed from fixture
+     *  - correct Store
+     *  - correct Results
+     *  - correct Uses
+     *  - correct Synonym
+     *  - correct Redirect URL
+     *  - correct Suggested Terms
+     *
+     * @param CatalogSearchIndex $indexPage
+     * @param CatalogSearchQuery $searchTerm
+     * @return void
+     */
+    public function processAssert(CatalogSearchIndex $indexPage, CatalogSearchQuery $searchTerm)
+    {
+        $grid = $indexPage->open()->getGrid();
+        $filters = [
+            'search_query' => $searchTerm->getQueryText(),
+            'store_id' => $searchTerm->getStoreId(),
+            'results_from' => $searchTerm->getNumResults(),
+            'popularity_from' => $searchTerm->getPopularity(),
+            'synonym_for' => $searchTerm->getSynonymFor(),
+            'redirect' => $searchTerm->getRedirect(),
+            'display_in_terms' => strtolower($searchTerm->getDisplayInTerms())
+        ];
+
+        $grid->search($filters);
+        unset($filters['store_id']);
+        \PHPUnit_Framework_Assert::assertTrue(
+            $grid->isRowVisible($filters),
+            'Row terms according to the filters is not found.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Row term according to the filters is not found.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermOnFrontend.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermOnFrontend.php
new file mode 100644
index 0000000000000000000000000000000000000000..2cf3f0dc73368f6aec5e8f7eaa06c350d99b2d1c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermOnFrontend.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\CatalogSearch\Test\Constraint;
+
+use Mtf\Client\Browser;
+use Magento\Cms\Test\Page\CmsIndex;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Block\Search;
+use Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery;
+
+/**
+ * Class AssertSearchTermOnFrontend
+ * Assert that after save a search term
+ */
+class AssertSearchTermOnFrontend extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'high';
+
+    /**
+     * Search block on CMS index page
+     *
+     * @var Search
+     */
+    protected $searchBlock;
+
+    /**
+     * Assert that after save a search term:
+     *  - it displays in the Search field at the top of the page if type set of characters passed from fixture
+     *  - after click 'Go' of Search field opens a results page if it was not specified Redirect URL
+     *  - after click 'Go' of Search field a customer search redirects to a specific page (passed from fixture)
+     *    if it was specified Redirect URL
+     *
+     * @param CmsIndex $cmsIndex
+     * @param CatalogSearchQuery $searchTerm
+     * @param Browser $browser
+     * @return void
+     */
+    public function processAssert(CmsIndex $cmsIndex, CatalogSearchQuery $searchTerm, Browser $browser)
+    {
+        $errors = [];
+        $this->searchBlock = $cmsIndex->open()->getSearchBlock();
+
+        if ($searchTerm->hasData('display_in_terms') && $searchTerm->getDisplayInTerms() === 'Yes') {
+            $errors = $this->checkSuggestSearch($searchTerm);
+        }
+
+        $this->searchBlock->search($searchTerm->getQueryText());
+        $windowUrl = $browser->getUrl();
+        $redirectUrl = $searchTerm->getRedirect();
+        if ($windowUrl !== $redirectUrl) {
+            $errors[] = '- url window (' . $windowUrl . ') does not match the url redirect(' . $redirectUrl . ')';
+        }
+
+        \PHPUnit_Framework_Assert::assertEmpty(
+            $errors,
+            'When checking on the frontend "Search terms" arose following errors:' . PHP_EOL . implode(PHP_EOL, $errors)
+        );
+    }
+
+    /**
+     * Check suggest block visibility
+     *
+     * @param CatalogSearchQuery $searchTerm
+     * @return array
+     */
+    protected function checkSuggestSearch(CatalogSearchQuery $searchTerm)
+    {
+        $queryText = $searchTerm->getQueryText();
+        $this->searchBlock->fillSearch($queryText);
+        if ($searchTerm->hasData('num_results')) {
+            $isVisible = $this->searchBlock->isSuggestSearchVisible(
+                $queryText,
+                $searchTerm->getNumResults()
+            );
+        } else {
+            $isVisible = $this->searchBlock->isSuggestSearchVisible($queryText);
+        }
+
+        return $isVisible ? [] : ['- block "Suggest Search" when searching was not found'];
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Checking "Search terms" on frontend successful.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSuccessSaveMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..4e68188532eaaba4a47a8d2f1ce54ca08dab7d76
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSuccessSaveMessage.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\CatalogSearch\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\CatalogSearch\Test\Page\Adminhtml\CatalogSearchIndex;
+
+/**
+ * Class AssertSearchTermSuccessSaveMessage
+ * Assert that success message is displayed after search term save
+ */
+class AssertSearchTermSuccessSaveMessage extends AbstractConstraint
+{
+    /**
+     * Text value to be checked
+     */
+    const SUCCESS_MESSAGE = 'You saved the search term.';
+
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'high';
+
+    /**
+     * Assert that success message is displayed after search term save
+     *
+     * @param CatalogSearchIndex $indexPage
+     * @return void
+     */
+    public function processAssert(CatalogSearchIndex $indexPage)
+    {
+        $actualMessage = $indexPage->getMessagesBlock()->getSuccessMessages();
+        \PHPUnit_Framework_Assert::assertEquals(
+            self::SUCCESS_MESSAGE,
+            $actualMessage,
+            'Wrong success message is displayed.'
+            . PHP_EOL . "Expected: " . self::SUCCESS_MESSAGE
+            . PHP_EOL . "Actual: " . $actualMessage
+        );
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Search term success save message is present.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSynonymOnFrontend.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSynonymOnFrontend.php
new file mode 100644
index 0000000000000000000000000000000000000000..9734bb43e33e80962b0a214e58741a12abc16572
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSynonymOnFrontend.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\CatalogSearch\Test\Constraint;
+
+use Mtf\Client\Browser;
+use Magento\Cms\Test\Page\CmsIndex;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery;
+
+/**
+ * Class AssertSearchTermSynonymOnFrontend
+ * Assert that you will be redirected to url from dataset
+ */
+class AssertSearchTermSynonymOnFrontend extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'high';
+
+    /**
+     * Assert that you will be redirected to url from dataset
+     *
+     * @param CmsIndex $cmsIndex
+     * @param Browser $browser
+     * @param CatalogSearchQuery $searchTerm
+     * @return void
+     */
+    public function processAssert(CmsIndex $cmsIndex, Browser $browser, CatalogSearchQuery $searchTerm)
+    {
+        $cmsIndex->open()->getSearchBlock()->search($searchTerm->getSynonymFor());
+        $windowUrl = $browser->getUrl();
+        $redirectUrl = $searchTerm->getRedirect();
+        \PHPUnit_Framework_Assert::assertEquals(
+            $windowUrl,
+            $redirectUrl,
+            'Redirect by synonym was not executed.'
+            . PHP_EOL . "Expected: " . $redirectUrl
+            . PHP_EOL . "Actual: " . $windowUrl
+        );
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Redirect by synonym executed successfully.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/Adminhtml/CatalogSearchEdit.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/Adminhtml/CatalogSearchEdit.php
new file mode 100644
index 0000000000000000000000000000000000000000..a0fb893070741b6d86ce549b2ab4c44ab2245275
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/Adminhtml/CatalogSearchEdit.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\CatalogSearch\Test\Page\Adminhtml;
+
+use Mtf\Page\BackendPage;
+
+/**
+ * Class CatalogSearchEdit
+ */
+class CatalogSearchEdit extends BackendPage
+{
+    const MCA = 'catalog/search/edit';
+
+    protected $_blocks = [
+        'form' => [
+            'name' => 'form',
+            'class' => 'Magento\CatalogSearch\Test\Block\Adminhtml\Edit\SearchTermForm',
+            'locator' => '#edit_form',
+            'strategy' => 'css selector',
+        ],
+        'formPageActions' => [
+            'name' => 'formPageActions',
+            'class' => 'Magento\Backend\Test\Block\FormPageActions',
+            'locator' => '.page-main-actions',
+            'strategy' => 'css selector',
+        ],
+    ];
+
+    /**
+     * @return \Magento\CatalogSearch\Test\Block\Adminhtml\Edit\SearchTermForm
+     */
+    public function getForm()
+    {
+        return $this->getBlockInstance('form');
+    }
+
+    /**
+     * @return \Magento\Backend\Test\Block\FormPageActions
+     */
+    public function getFormPageActions()
+    {
+        return $this->getBlockInstance('formPageActions');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/Adminhtml/CatalogSearchEdit.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/Adminhtml/CatalogSearchEdit.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6cd1827cc54cb57e0853bb7be077ffa9e0a297e9
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/Adminhtml/CatalogSearchEdit.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<page mca="catalog/search/edit" >
+    <block>
+        <name>form</name>
+        <class>Magento\CatalogSearch\Test\Block\Adminhtml\Edit\SearchTermForm</class>
+        <locator>#edit_form</locator>
+        <strategy>css selector</strategy>
+    </block>
+    <block>
+        <name>formPageActions</name>
+        <class>Magento\Backend\Test\Block\FormPageActions</class>
+        <locator>.page-main-actions</locator>
+        <strategy>css selector</strategy>
+    </block>
+</page>
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/Adminhtml/CatalogSearchIndex.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/Adminhtml/CatalogSearchIndex.php
new file mode 100644
index 0000000000000000000000000000000000000000..65382917327be175741e637deb0c818b35447a84
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/Adminhtml/CatalogSearchIndex.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\CatalogSearch\Test\Page\Adminhtml;
+
+use Mtf\Page\BackendPage;
+
+/**
+ * Class CatalogSearchIndex
+ */
+class CatalogSearchIndex extends BackendPage
+{
+    const MCA = 'catalog/search/index';
+
+    protected $_blocks = [
+        'grid' => [
+            'name' => 'grid',
+            'class' => 'Magento\CatalogSearch\Test\Block\Adminhtml\Grid',
+            'locator' => '#catalog_search_grid',
+            'strategy' => 'css selector',
+        ],
+        'gridPageActions' => [
+            'name' => 'gridPageActions',
+            'class' => 'Magento\Backend\Test\Block\GridPageActions',
+            'locator' => '.page-main-actions',
+            'strategy' => 'css selector',
+        ],
+        'messagesBlock' => [
+            'name' => 'messagesBlock',
+            'class' => 'Magento\Core\Test\Block\Messages',
+            'locator' => '.page-main-actions',
+            'strategy' => 'css selector',
+        ],
+    ];
+
+    /**
+     * @return \Magento\CatalogSearch\Test\Block\Adminhtml\Grid
+     */
+    public function getGrid()
+    {
+        return $this->getBlockInstance('grid');
+    }
+
+    /**
+     * @return \Magento\Backend\Test\Block\GridPageActions
+     */
+    public function getGridPageActions()
+    {
+        return $this->getBlockInstance('gridPageActions');
+    }
+
+    /**
+     * @return \Magento\Core\Test\Block\Messages
+     */
+    public function getMessagesBlock()
+    {
+        return $this->getBlockInstance('messagesBlock');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/Adminhtml/CatalogSearchIndex.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/Adminhtml/CatalogSearchIndex.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a1edd489ab49dc4f94eec0cdf921014d85c96a9e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/Adminhtml/CatalogSearchIndex.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<page mca="catalog/search/index" >
+    <block>
+        <name>grid</name>
+        <class>Magento\CatalogSearch\Test\Block\Adminhtml\Grid</class>
+        <locator>#catalog_search_grid</locator>
+        <strategy>css selector</strategy>
+    </block>
+    <block>
+        <name>gridPageActions</name>
+        <class>Magento\Backend\Test\Block\GridPageActions</class>
+        <locator>.page-main-actions</locator>
+        <strategy>css selector</strategy>
+    </block>
+    <block>
+        <name>messagesBlock</name>
+        <class>Magento\Core\Test\Block\Messages</class>
+        <locator>.page-main-actions</locator>
+        <strategy>css selector</strategy>
+    </block>
+</page>
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/CatalogsearchResult.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/CatalogsearchResult.php
index d6f4bcd3b7f273ea7691932fd6a0158db5b860e9..5bbd6b735ec1265323e508415b8c259f076b6ca5 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/CatalogsearchResult.php
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/CatalogsearchResult.php
@@ -40,6 +40,12 @@ class CatalogsearchResult extends FrontendPage
             'locator' => '.search.results',
             'strategy' => 'css selector',
         ],
+        'toolbar' => [
+            'name' => 'toolbar',
+            'class' => 'Magento\Catalog\Test\Block\Product\ProductList\Toolbar',
+            'locator' => '.toolbar.products',
+            'strategy' => 'css selector',
+        ],
     ];
 
     /**
@@ -49,4 +55,12 @@ class CatalogsearchResult extends FrontendPage
     {
         return $this->getBlockInstance('listProductBlock');
     }
+
+    /**
+     * @return \Magento\Catalog\Test\Block\Product\ProductList\Toolbar
+     */
+    public function getToolbar()
+    {
+        return $this->getBlockInstance('toolbar');
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/CatalogsearchResult.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/CatalogsearchResult.xml
index 3ed22b1488a608cd722183e01014f94b154f24ff..dbaf99afe1bad4d10253df277c4d84c88bd99422 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/CatalogsearchResult.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Page/CatalogsearchResult.xml
@@ -30,4 +30,10 @@
         <locator>.search.results</locator>
         <strategy>css selector</strategy>
     </block>
+    <block>
+        <name>toolbar</name>
+        <class>Magento\Catalog\Test\Block\Product\ProductList\Toolbar</class>
+        <locator>.toolbar.products</locator>
+        <strategy>css selector</strategy>
+    </block>
 </page>
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/CreateSearchTermEntityTest.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/CreateSearchTermEntityTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..bf3c3b0703beab9a11ad727ecd363dce0a8d5d80
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/CreateSearchTermEntityTest.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\CatalogSearch\Test\TestCase;
+
+use Mtf\TestCase\Injectable;
+use Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery;
+use Magento\CatalogSearch\Test\Page\Adminhtml\CatalogSearchEdit;
+use Magento\CatalogSearch\Test\Page\Adminhtml\CatalogSearchIndex;
+
+/**
+ * Test Creation for CreateSearchTermEntity
+ *
+ * Test Flow:
+ *
+ * Preconditions:
+ * 1. Product is created
+ *
+ * Steps:
+ * 1. Go to backend as admin user
+ * 4. Navigate to Marketing->SEO&Search->Search Terms
+ * 5. Click "Add New Search Term" button
+ * 6. Fill out all data according to dataset
+ * 7. Save the Search Term
+ * 8. Perform all assertions
+ *
+ * @group Search Terms (MX)
+ * @ZephyrId MAGETWO-26165
+ */
+class CreateSearchTermEntityTest extends Injectable
+{
+    /**
+     * Search term page
+     *
+     * @var CatalogSearchIndex
+     */
+    protected $indexPage;
+
+    /**
+     * Search term edit page
+     *
+     * @var CatalogSearchEdit
+     */
+    protected $editPage;
+
+    /**
+     * Inject pages
+     *
+     * @param CatalogSearchIndex $indexPage
+     * @param CatalogSearchEdit $editPage
+     * @return void
+     */
+    public function __inject(CatalogSearchIndex $indexPage, CatalogSearchEdit $editPage)
+    {
+        $this->indexPage = $indexPage;
+        $this->editPage = $editPage;
+    }
+
+    /**
+     * Run create search term test
+     *
+     * @param CatalogSearchQuery $searchTerm
+     * @return void
+     */
+    public function test(CatalogSearchQuery $searchTerm)
+    {
+        $this->markTestIncomplete('MAGETWO-26170');
+        // Steps
+        $this->indexPage->open();
+        $this->indexPage->getGridPageActions()->addNew();
+        $this->editPage->getForm()->fill($searchTerm);
+        $this->editPage->getFormPageActions()->save();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/CreateSearchTermEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/CreateSearchTermEntityTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..124f69344b39ade304e3ca3e188eb713caba2d52
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/CreateSearchTermEntityTest/test.csv
@@ -0,0 +1,2 @@
+"searchTerm/data/query_text/value";"searchTerm/data/store_id";"searchTerm/data/synonym_for";"searchTerm/data/redirect";"searchTerm/data/display_in_terms";"constraint"
+"catalogProductSimple::getSku";"Main Website/Main Website Store/Default Store View";"Search Term Synonym %isolation%";"http://example.com/";"No";"assertSearchTermSuccessSaveMessage, assertSearchTermInGrid, assertSearchTermForm, assertSearchTermOnFrontend, assertSearchTermSynonymOnFrontend"
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/EditSearchTermEntityTest.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/EditSearchTermEntityTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e7beddab532a7574f8d873943c42157e235cfce7
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/EditSearchTermEntityTest.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\CatalogSearch\Test\TestCase;
+
+use Mtf\TestCase\Injectable;
+use Magento\Cms\Test\Page\CmsIndex;
+use Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery;
+use Magento\CatalogSearch\Test\Page\Adminhtml\CatalogSearchEdit;
+use Magento\CatalogSearch\Test\Page\Adminhtml\CatalogSearchIndex;
+
+/**
+ * Test Creation for EditSearchTermEntity
+ *
+ * Test Flow:
+ *
+ * Preconditions:
+ * 1. Product is created
+ *
+ * Steps:
+ * 1. Go to frontend
+ * 2. Test word into the Search field at the top of the page and click Go
+ * 3. Go to backend as admin user
+ * 4. Navigate to Marketing->SEO&Search->Search Terms
+ * 5. Click "Edit" link of just added test word search term
+ * 6. Fill out all data according to dataset
+ * 7. Save the Search Term
+ * 8. Perform all assertions
+ *
+ * @group Search Terms (MX)
+ * @ZephyrId MAGETWO-26100
+ */
+class EditSearchTermEntityTest extends Injectable
+{
+    /**
+     * CMS index page
+     *
+     * @var CmsIndex
+     */
+    protected $cmsIndex;
+
+    /**
+     * Search term page
+     *
+     * @var CatalogSearchIndex
+     */
+    protected $indexPage;
+
+    /**
+     * Search term edit page
+     *
+     * @var CatalogSearchEdit
+     */
+    protected $editPage;
+
+    /**
+     * Inject pages
+     *
+     * @param CmsIndex $cmsIndex
+     * @param CatalogSearchIndex $indexPage
+     * @param CatalogSearchEdit $editPage
+     * @return void
+     */
+    public function __inject(
+        CmsIndex $cmsIndex,
+        CatalogSearchIndex $indexPage,
+        CatalogSearchEdit $editPage
+    ) {
+        $this->cmsIndex = $cmsIndex;
+        $this->indexPage = $indexPage;
+        $this->editPage = $editPage;
+    }
+
+    /**
+     * Run edit search term test
+     *
+     * @param CatalogSearchQuery $searchTerm
+     * @return void
+     */
+    public function test(CatalogSearchQuery $searchTerm)
+    {
+        // Preconditions
+        $searchText = $searchTerm->getQueryText();
+        // Steps
+        $this->cmsIndex->open()->getSearchBlock()->search($searchText);
+        $this->indexPage->open()->getGrid()->searchAndOpen(['search_query' => $searchText]);
+        $this->editPage->getForm()->fill($searchTerm);
+        $this->editPage->getFormPageActions()->save();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/EditSearchTermEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/EditSearchTermEntityTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..c6941e465c76df0ca1bbebdf41f6eb5910c7fddc
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/EditSearchTermEntityTest/test.csv
@@ -0,0 +1,2 @@
+"searchTerm/data/query_text/value";"searchTerm/data/store_id";"searchTerm/data/num_results";"searchTerm/data/popularity";"searchTerm/data/synonym_for";"searchTerm/data/redirect";"searchTerm/data/display_in_terms";"constraint"
+"catalogProductSimple::getSku";"Main Website/Main Website Store/Default Store View";1;20;"simple";"http://example.com/";"No";"assertSearchTermForm, assertSearchTermInGrid, assertSearchTermOnFrontend"
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/etc/global/constraint.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/etc/global/constraint.xml
index 7f383cc9f8b9b3af2a8cec41e68b9dad537ebeb9..dbe33dd650d840b1b547d5e3cddb6cecf31910c0 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/etc/global/constraint.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/etc/global/constraint.xml
@@ -43,6 +43,45 @@
         <require>
             <cmsIndex class="Magento\Cms\Test\Page\CmsIndex" />
             <catalogSearch class="Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery" />
+            <editPage class="Magento\CatalogSearch\Test\Page\Adminhtml\CatalogSearchEdit" />
         </require>
     </assertCatalogSearchResult>
+    <assertSearchTermForm module="Magento_CatalogSearch">
+        <severeness>high</severeness>
+        <require>
+            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex" />
+            <searchTerm class="Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery" />
+            <editPage class="Magento\CatalogSearch\Test\Page\Adminhtml\CatalogSearchEdit" />
+        </require>
+    </assertSearchTermForm>
+    <assertSearchTermInGrid module="Magento_CatalogSearch">
+        <severeness>high</severeness>
+        <require>
+            <indexPage class="Magento\CatalogSearch\Test\Page\Adminhtml\CatalogSearchIndex" />
+            <editPage class="Magento\CatalogSearch\Test\Page\Adminhtml\CatalogSearchEdit" />
+            <searchTerm class="Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery" />
+        </require>
+    </assertSearchTermInGrid>
+    <assertSearchTermOnFrontend module="Magento_CatalogSearch">
+        <severeness>high</severeness>
+        <require>
+            <searchTerm class="Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery" />
+            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex" />
+            <browser class="Mtf\Client\Browser" />
+        </require>
+    </assertSearchTermOnFrontend>
+    <assertSearchTermSuccessSaveMessage  module="Magento_CatalogSearch">
+        <severeness>high</severeness>
+        <require>
+            <indexPage class="Magento\CatalogSearch\Test\Page\Adminhtml\CatalogSearchIndex" />
+        </require>
+    </assertSearchTermSuccessSaveMessage>
+    <assertSearchTermSynonymOnFrontend  module="Magento_CatalogSearch">
+        <severeness>high</severeness>
+        <require>
+            <searchTerm class="Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery" />
+            <cmsIndex class="Magento\Cms\Test\Page\CmsIndex" />
+            <browser class="Mtf\Client\Browser" />
+        </require>
+    </assertSearchTermSynonymOnFrontend>
 </constraint>
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/etc/global/page.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/etc/global/page.xml
index 5c581d37d87fefd8f3cb0b2a72e18308966d2b90..ba505ac72d4a2a33d9d364ddd13a8b12b47d3d78 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/etc/global/page.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/etc/global/page.xml
@@ -28,13 +28,14 @@
         <mca>catalogsearch/result</mca>
         <class>Magento\CatalogSearch\Test\Page\CatalogsearchResult</class>
     </catalogsearchResult>
-    <advanced>
-        <mca>catalogsearch/advanced</mca>
-        <class>Magento\CatalogSearch\Test\Page\Advanced</class>
-    </advanced>
-    <result>
-        <mca>catalogsearch/advanced/result</mca>
-        <area>advanced</area>
-        <class>Magento\CatalogSearch\Test\Page\Advanced\Result</class>
-    </result>
+    <catalogSearchIndex>
+        <area>adminhtml</area>
+        <mca>catalog/search/index</mca>
+        <class>Magento\CatalogSearch\Test\Page\Adminhtml\CatalogSearchIndex</class>
+    </catalogSearchIndex>
+    <catalogSearchEdit>
+        <area>adminhtml</area>
+        <mca>catalog/search/edit</mca>
+        <class>Magento\CatalogSearch\Test\Page\Adminhtml\CatalogSearchEdit</class>
+    </catalogSearchEdit>
 </page>
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php
index 6518de4138b921f9c5b5c93207ef1f193307c7dd..fc3b9146b1c8d16c1a5b329cceacf0f61fb1b249 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php
@@ -58,21 +58,21 @@ class Cart extends Block
      *
      * @var string
      */
-    protected $itemSubTotalSelector = '//td[@class="col subtotal excl tax"]//span[@class="price"]';
+    protected $itemSubTotalSelector = '//td[@class="col subtotal"]//*[@class="excl tax"]//span[@class="price"]';
 
     /**
      * Cart item unit price xpath selector
      *
      * @var string
      */
-    protected $itemUnitPriceSelector = '//td[@class="col price excl tax"]//span[@class="price"]';
+    protected $itemUnitPriceSelector = '//td[@class="col price"]//*[@class="excl tax"]//span[@class="price"]';
 
     /**
      * Unit Price value
      *
      * @var string
      */
-    protected $cartProductPrice = '//tr[string(td/div/strong/a)="%s"]/td[@class="col price excl tax"]/span/span';
+    protected $cartProductPrice = '//tr[string(td/div/strong/a)="%s"]/td[@class="col price"]/*[@class="excl tax"]/span';
 
     /**
      * 'Update Shopping Cart' button
@@ -86,14 +86,21 @@ class Cart extends Block
      *
      * @var string
      */
-    protected $productQty = '//input[@type="number" and @title="Qty"]';
+    protected $productQty = './/input[@type="number" and @title="Qty"]';
 
     /**
      * Cart item selector
      *
      * @var string
      */
-    protected $cartItem = '//tr[normalize-space(td)="%s"]';
+    protected $cartItem = './/tr[td//*[contains(.,"%s")]]';
+
+    /**
+     * Get bundle options
+     *
+     * @var string
+     */
+    protected $bundleOptions = './/dl[contains(@class, "cart-item-options")]/dd[%d]/span[@class="price"][%d]';
 
     /**
      * Get sub-total for the specified item in the cart
@@ -268,7 +275,7 @@ class Cart extends Block
         if ($product instanceof ConfigurableProduct) {
             $productOptions = $product->getProductOptions();
             if (!empty($productOptions)) {
-                $productName = $productName . ' ' . key($productOptions) . ' ' . current($productOptions);
+                $productName = $productName . '")] and *[contains(.,"' . current($productOptions);
             }
         }
         return $productName;
@@ -333,4 +340,18 @@ class Cart extends Block
         preg_match("/^\\D*\\s*([\\d,\\.]+)\\s*\\D*$/", $price, $matches);
         return (isset($matches[1])) ? $matches[1] : null;
     }
+
+    /**
+     * Get item Bundle options
+     *
+     * @param int $index
+     * @param int $itemIndex
+     * @param string $currency
+     * @return string
+     */
+    public function getPriceBundleOptions($index, $itemIndex = 1, $currency = '$')
+    {
+        $formatPrice = sprintf($this->bundleOptions, $index, $itemIndex);
+        return trim($this->_rootElement->find($formatPrice, Locator::SELECTOR_XPATH)->getText(), $currency);
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsBlock/CmsBlockInterface.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsBlock/CmsBlockInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..e4ae992c791b484a375648851cf577c713ad1ecc
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsBlock/CmsBlockInterface.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Cms\Test\Handler\CmsBlock;
+
+use Mtf\Handler\HandlerInterface;
+
+/**
+ * Interface CmsBlockInterface
+ */
+interface CmsBlockInterface extends HandlerInterface
+{
+    //
+}
diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsBlock/Curl.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsBlock/Curl.php
new file mode 100644
index 0000000000000000000000000000000000000000..54bb378e9ac1f2681d1058edadea9c1b13a91e5c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsBlock/Curl.php
@@ -0,0 +1,114 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Cms\Test\Handler\CmsBlock;
+
+use Mtf\System\Config;
+use Mtf\Fixture\FixtureInterface;
+use Mtf\Util\Protocol\CurlInterface;
+use Mtf\Util\Protocol\CurlTransport;
+use Magento\Backend\Test\Handler\Extractor;
+use Mtf\Util\Protocol\CurlTransport\BackendDecorator;
+use Mtf\Handler\Curl as AbstractCurl;
+
+/**
+ * Class Curl
+ * Curl handler for creating CMS Block
+ */
+class Curl extends AbstractCurl implements CmsBlockInterface
+{
+    /**
+     * Url for saving data
+     *
+     * @var string
+     */
+    protected $saveUrl = 'cms/block/save';
+
+    /**
+     * Mapping values for data
+     *
+     * @var array
+     */
+    protected $mappingData = [
+        'is_active' => [
+            'Enabled' => 1,
+            'Disabled' => 0,
+        ],
+    ];
+
+    /**
+     * Mapping values for Stores
+     *
+     * @var array
+     */
+    protected $stores = [
+        'All Store Views' => 0
+    ];
+
+    /**
+     * POST request for creating CMS Block
+     *
+     * @param FixtureInterface|null $fixture [optional]
+     * @return array
+     * @throws \Exception
+     */
+    public function persist(FixtureInterface $fixture = null)
+    {
+        $data = $this->prepareData($fixture);
+        $url = $_ENV['app_backend_url'] . $this->saveUrl;
+        $curl = new BackendDecorator(new CurlTransport(), new Config());
+        $curl->write(CurlInterface::POST, $url, '1.0', [], $data);
+        $response = $curl->read();
+        $curl->close();
+        if (!strpos($response, 'data-ui-id="messages-message-success"')) {
+            throw new \Exception("CMS Block entity creating by curl handler was not successful! Response: $response");
+        }
+
+        $url = 'cms/block/index/sort/creation_time/dir/desc';
+        $regExpPattern = '@^.*block_id\/(\d+)\/.*' . $fixture->getTitle() . '@ms';
+        $extractor = new Extractor($url, $regExpPattern);
+
+        return ['block_id' => $extractor->getData()[1]];
+    }
+
+    /**
+     * Prepare data from text to values
+     *
+     * @param FixtureInterface $fixture
+     * @return array
+     */
+    protected function prepareData($fixture)
+    {
+        $data = $this->replaceMappingData($fixture->getData());
+        if (isset($data['stores'])) {
+            $stores = [];
+            foreach ($data['stores'] as $store) {
+                $stores[] = isset($this->stores[$store]) ? $this->stores[$store] : $store;
+            }
+            $data['stores'] = $stores;
+        }
+
+        return $data;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.php
index 0fd1481fc81776aa7040dae449455169abb20c31..934ef479b7109f8213fb4344305de916c962be02 100644
--- a/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.php
+++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.php
@@ -76,6 +76,18 @@ class CmsIndex extends FrontendPage
             'locator' => '[data-block="minicart"]',
             'strategy' => 'css selector',
         ],
+        'compareProductsBlock' => [
+            'name' => 'compareProductsBlock',
+            'class' => 'Magento\Catalog\Test\Block\Product\Compare\Sidebar',
+            'locator' => '.sidebar.sidebar-additional',
+            'strategy' => 'css selector',
+        ],
+        'mainContentBlock' => [
+            'name' => 'mainContentBlock',
+            'class' => 'Magento\Cms\Test\Block\Page',
+            'locator' => '#maincontent',
+            'strategy' => 'css selector',
+        ],
     ];
 
     /**
@@ -133,4 +145,19 @@ class CmsIndex extends FrontendPage
     {
         return $this->getBlockInstance('cartSidebarBlock');
     }
+
+    /**
+     * @return \Magento\Catalog\Test\Block\Product\Compare\Sidebar
+     */
+    public function getCompareProductsBlock()
+    {
+        return $this->getBlockInstance('compareProductsBlock');
+    }
+    /**
+     * @return \Magento\Cms\Test\Block\Page
+     */
+    public function getMainContentBlock()
+    {
+        return $this->getBlockInstance('mainContentBlock');
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.xml
index f2c089e48bf893f443ee99601e3ed4b78603500e..57462d1fde391df156ce03d5929ed350c928481a 100644
--- a/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.xml
+++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.xml
@@ -33,7 +33,7 @@
     <block>
         <name>topmenu</name>
         <class>Magento\Theme\Test\Block\Html\Topmenu</class>
-        <locator>[role=navigation]</locator>
+        <locator>[role="navigation"]</locator>
         <strategy>css selector</strategy>
     </block>
     <block>
@@ -45,7 +45,7 @@
     <block>
         <name>footerBlock</name>
         <class>Magento\Theme\Test\Block\Html\Footer</class>
-        <locator>footer.page-footer</locator>
+        <locator>footer.page.footer</locator>
         <strategy>css selector</strategy>
     </block>
     <block>
@@ -66,4 +66,10 @@
         <locator>[data-block="minicart"]</locator>
         <strategy>css selector</strategy>
     </block>
+    <block>
+        <name>compareProductsBlock</name>
+        <class>Magento\Catalog\Test\Block\Product\Compare\Sidebar</class>
+        <locator>.sidebar.sidebar-additional</locator>
+        <strategy>css selector</strategy>
+    </block>
 </page>
diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsPage.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsPage.xml
new file mode 100644
index 0000000000000000000000000000000000000000..682a389cc83a21130158a8dfcfaf53b15efff5e8
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsPage.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<page mca="cms/page" >
+    <block>
+        <name>cmsPageBlock</name>
+        <class>Magento\Cms\Test\Block\Page</class>
+        <locator>.page.main</locator>
+        <strategy>css selector</strategy>
+    </block>
+</page>
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config.php
index e33f17145d58b7082ba9d56371a70326879cfd3b..ebf6a8a5209755a01d1d2b1d4056049a356d2ad0 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config.php
@@ -77,6 +77,41 @@ class Config extends Tab
      */
     protected $attributeTab = './/*[@data-role="configurable-attribute"]//*[text()="%attributeTab%"]';
 
+    /**
+     * XPath Selector attribute variations row content
+     *
+     * @var string
+     */
+    protected $activeButtonSelector = '//*[contains(@class,"fieldset-wrapper-title")]//*[@class="title"]';
+
+    /**
+     * XPath Selector attribute variations row
+     *
+     * @var string
+     */
+    protected $rowSelector = '//div[contains(@data-role,"configurable-attribute") and position()=%d]';
+
+    /**
+     * XPath Selector attribute options row
+     *
+     * @var string
+     */
+    protected $rowOptions = './/tbody/tr[contains(@data-role,"option-container") and position()=%d]';
+
+    /**
+     * XPath Selector attribute options row
+     *
+     * @var string
+     */
+    protected $rowMatrix = './/tbody/tr[contains(@data-role,"row") and position()=%d]';
+
+    /**
+     * CSS selector variations label
+     *
+     * @var string
+     */
+    protected $labelSelector = '.store-label';
+
     /**
      * Get attribute block
      *
@@ -197,4 +232,73 @@ class Config extends Tab
             $attribute->click();
         }
     }
+
+    /**
+     * Get data of tab
+     *
+     * @param array|null $fields [optional]
+     * @param Element|null $element [optional]
+     * @return array
+     */
+    public function getDataFormTab($fields = null, Element $element = null)
+    {
+        $dataResult = [];
+        if (isset($fields['configurable_attributes_data']['value']['attributes_data'])) {
+            $field['attributes_data']['value'] = $fields['configurable_attributes_data']['value']['attributes_data'];
+            $data = $this->dataMapping($field)['attributes_data'];
+            $variationsBlock = $this->_rootElement->find($data['selector']);
+
+            foreach ($data['value'] as $key => $value) {
+                ++$key;
+                $this->openVariation($key, $variationsBlock);
+                $row = $variationsBlock->find(sprintf($this->rowSelector, $key), Locator::SELECTOR_XPATH);
+                --$key;
+                $dataResult['attributes_data'][$key]['title'] = $row->find($this->labelSelector)->getValue();
+                $dataResult['attributes_data'][$key]['options'] = [];
+                foreach ($value['options'] as $optionKey => $option) {
+                    ++$optionKey;
+                    $optionsForm = $this->blockFactory->create(
+                        'Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Super\Options',
+                        ['element' => $row->find(sprintf($this->rowOptions, $optionKey), Locator::SELECTOR_XPATH)]
+                    );
+                    $dataResult['attributes_data'][$key]['options'][] = $optionsForm->getDataOptions($option);
+                }
+            }
+        }
+        if (isset($fields['configurable_attributes_data']['value']['matrix'])) {
+            $field['matrix']['value'] = $fields['configurable_attributes_data']['value']['matrix'];
+            $data = $this->dataMapping($field)['matrix'];
+            $matrixBlock = $this->_rootElement->find($data['selector']);
+
+            $index = 1;
+            foreach ($data['value'] as $key => $value) {
+                $matrixCell = $this->blockFactory->create(
+                    'Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Super\Matrix',
+                    ['element' => $matrixBlock->find(sprintf($this->rowMatrix, $index), Locator::SELECTOR_XPATH)]
+                );
+                $dataResult['matrix'][$key] = $matrixCell->getDataOptions();
+                ++$index;
+            }
+        }
+
+        return ['configurable_attributes_data' => $dataResult];
+    }
+
+    /**
+     * Active variation tab
+     *
+     * @param int $row
+     * @param Element $variationsBlock
+     * @return void
+     */
+    protected function openVariation($row, Element $variationsBlock)
+    {
+        $element = $variationsBlock->find(
+            sprintf($this->rowSelector, $row) . $this->activeButtonSelector,
+            Locator::SELECTOR_XPATH
+        );
+        if ($element->isVisible()) {
+            $element->click();
+        }
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Matrix.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Matrix.php
new file mode 100644
index 0000000000000000000000000000000000000000..c0aecc288f0885727a0d27d2c829f57085326cbc
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Matrix.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Super;
+
+use Mtf\Client\Element;
+use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options as CatalogOptions;
+
+/**
+ * Class Matrix
+ * Matrix row form
+ */
+class Matrix extends CatalogOptions
+{
+    /**
+     * CSS selector data cell
+     *
+     * @var string
+     */
+    protected $cellSelector = 'td:nth-child(%d)';
+
+    /**
+     * Field name mapping
+     *
+     * @var array
+     */
+    protected $fieldNameMapping = [
+        3 => 'name',
+        4 => 'sku',
+        5 => 'price',
+        6 => 'qty',
+        7 => 'weight'
+    ];
+
+    /**
+     * Getting product matrix data form on the product form
+     *
+     * @param array|null $fields [optional]
+     * @param Element|null $element [optional]
+     * @return array
+     */
+    public function getDataOptions(array $fields = null, Element $element = null)
+    {
+        $element = $element === null ? $this->_rootElement : $element;
+        $mapping = $this->dataMapping($fields);
+        $data = $this->_getData($mapping, $element);
+
+        $column = 3;
+        $cell = $element->find(sprintf($this->cellSelector, $column));
+        $data['options_names'] = [];
+        while ($cell->isVisible()) {
+            if (isset($this->fieldNameMapping[$column])) {
+                $data[$this->fieldNameMapping[$column]] = $cell->getText();
+            } else {
+                $data['options_names'][] = $cell->getText();
+            }
+            $cell = $element->find(sprintf($this->cellSelector, ++$column));
+        }
+
+        return $data;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Matrix.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Matrix.xml
new file mode 100644
index 0000000000000000000000000000000000000000..211a7cc5252b6f14a319caf84ed0ea00f0ad9764
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Matrix.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <display>
+            <selector>td [name$='associated_product_ids[]']</selector>
+            <input>checkbox</input>
+        </display>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Options.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Options.php
new file mode 100644
index 0000000000000000000000000000000000000000..3749a1d246b9d071bc2f11b338f78f63786607b1
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Options.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Super;
+
+use Mtf\Client\Element;
+use Mtf\Client\Element\Locator;
+use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Options as CatalogOptions;
+
+/**
+ * Class Options
+ * Attribute options row form
+ */
+class Options extends CatalogOptions
+{
+    /**
+     * CSS selector name item
+     *
+     * @var string
+     */
+    protected $nameSelector = 'td[data-column="name"]';
+
+    /**
+     * XPath selector percent label
+     *
+     * @var string
+     */
+    protected $percentSelector = '//button[span[contains(text(),"%")]]';
+
+    /**
+     * Getting options data form on the product form
+     *
+     * @param array|null $fields [optional]
+     * @param Element|null $element [optional]
+     * @return array
+     */
+    public function getDataOptions(array $fields = null, Element $element = null)
+    {
+        $element = $element === null ? $this->_rootElement : $element;
+        $mapping = $this->dataMapping($fields);
+        $data = $this->_getData($mapping, $element);
+
+        $data['is_percent'] = 'No';
+        $percentElement = $element->find($this->percentSelector, Locator::SELECTOR_XPATH);
+        if ($percentElement->isVisible()) {
+            $data['is_percent'] = 'Yes';
+        }
+
+        $nameElement = $element->find($this->nameSelector);
+        if ($nameElement->isVisible()) {
+            $data['name'] = $nameElement->getText();
+        }
+
+        return $data;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Options.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Options.xml
new file mode 100644
index 0000000000000000000000000000000000000000..05c31e62d000cfcd3014e7097e8086b1b2509d66
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Options.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <pricing_value>
+            <selector>[name$='[pricing_value]']</selector>
+        </pricing_value>
+        <include>
+            <selector>[name$='[include]']</selector>
+            <input>checkbox</input>
+        </include>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.php
old mode 100644
new mode 100755
index 2cc1ac02d41fe3c805a36f6d8410d0b0ae396b41..98922c8272ffb128a2b202bbb444d8bf821ff3b0
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.php
@@ -28,6 +28,7 @@ use Mtf\Block\Mapper;
 use Mtf\Client\Element;
 use Mtf\Client\Browser;
 use Mtf\Factory\Factory;
+use Mtf\Fixture\FixtureInterface;
 use Mtf\Util\XmlConverter;
 use Mtf\Block\BlockFactory;
 use Mtf\Client\Element\Locator;
@@ -54,6 +55,13 @@ class ProductForm extends ParentForm
      */
     protected $newAttributeFrame = '#create_new_attribute_container';
 
+    /**
+     * New variation set button selector
+     *
+     * @var string
+     */
+    protected $newVariationSet = '[data-ui-id="admin-product-edit-tab-super-config-grid-container-add-attribute"]';
+
     /**
      * Variations tab selector
      *
@@ -126,14 +134,17 @@ class ProductForm extends ParentForm
     }
 
     /**
-     * Initialization categories before use in the form of
+     * Save product
      *
-     * @param CatalogCategory $category
-     * @return void
+     * @param FixtureInterface $fixture
+     * @return \Magento\Backend\Test\Block\Widget\Form|void
      */
-    public function setCategory(CatalogCategory $category)
+    public function save(FixtureInterface $fixture = null)
     {
-        $this->category = $category;
+        parent::save($fixture);
+        if ($this->getAffectedAttributeSetBlock()->isVisible()) {
+            $this->getAffectedAttributeSetBlock()->chooseAttributeSet($fixture);
+        }
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.xml
index eb831ebbe03b82b7cf434bc33769c103411ba5b6..68c9e8a73eb224bf7b1a9c92747e05252d04b0d6 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.xml
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.xml
@@ -68,5 +68,13 @@
         <class>\Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Super\Config</class>
         <selector>#product_info_tabs_product-details</selector>
         <strategy>css selector</strategy>
+        <fields>
+            <attributes_data>
+                <selector>#super_config-wrapper</selector>
+            </attributes_data>
+            <matrix>
+                <selector>#product-variations-matrix</selector>
+            </matrix>
+        </fields>
     </variations>
 </tabs>
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableInCart.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableInCart.php
old mode 100644
new mode 100755
index b4f2372942cd3a830170a8db95fcf40b991a494c..5e9e9c0ed584cc247c1f0e1072bdbe830531a7e9
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableInCart.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableInCart.php
@@ -30,7 +30,7 @@ use Magento\Catalog\Test\Page\Product\CatalogProductView;
 use Magento\ConfigurableProduct\Test\Fixture\CatalogProductConfigurable;
 
 /**
- * Class AssertProductInCart
+ * Class AssertConfigurableInCart
  */
 class AssertConfigurableInCart extends AbstractConstraint
 {
@@ -61,7 +61,7 @@ class AssertConfigurableInCart extends AbstractConstraint
         if (!empty($configurableData)) {
             $configurableOption = $catalogProductView->getCustomOptionsBlock();
             foreach ($configurableData['attributes_data'] as $attribute) {
-                $configurableOption->selectProductCustomOption(reset($attribute['options'])['name']);
+                $configurableOption->selectProductCustomOption($attribute['title']);
             }
         }
         $catalogProductView->getViewBlock()->clickAddToCart();
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php
old mode 100644
new mode 100755
index ec83346fc0876233cbcc69aadcb1c292faebc9af..db8340d3116829bba22fa20da4d28c28e506174a
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php
@@ -69,7 +69,7 @@ class AssertProductAttributeIsConfigurable extends AbstractConstraint
     ) {
         $this->attribute = !is_null($productAttribute) ? $productAttribute : $attribute;
         $productGrid->open();
-        $productGrid->getProductBlock()->addProduct('configurable');
+        $productGrid->getGridPageActionBlock()->addProduct('configurable');
 
         $productConfigurable = $fixtureFactory->createByCode(
             'catalogProductConfigurable',
@@ -87,7 +87,7 @@ class AssertProductAttributeIsConfigurable extends AbstractConstraint
         );
 
         $productBlockForm = $newProductPage->getForm();
-        $productBlockForm->fillProduct($productConfigurable);
+        $productBlockForm->fill($productConfigurable);
 
         \PHPUnit_Framework_Assert::assertTrue(
             $newProductPage->getForm()->findAttribute($this->attribute->getFrontendLabel()),
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductConfigurableDuplicateForm.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductConfigurableDuplicateForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..d66d28b2156a1c93ff501eef8332a80e5c5dd672
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductConfigurableDuplicateForm.php
@@ -0,0 +1,112 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\ConfigurableProduct\Test\Constraint;
+
+use Mtf\Fixture\FixtureInterface;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Catalog\Test\Constraint\AssertProductDuplicateForm;
+use Magento\ConfigurableProduct\Test\Page\Adminhtml\CatalogProductEdit;
+
+/**
+ * Class AssertProductConfigurableDuplicateForm
+ */
+class AssertProductConfigurableDuplicateForm extends AssertProductDuplicateForm
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert form data equals duplicate product configurable data
+     *
+     * @param FixtureInterface $product
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductEdit $productPage
+     * @return void
+     */
+    public function processAssert(
+        FixtureInterface $product,
+        CatalogProductIndex $productGrid,
+        CatalogProductEdit $productPage
+    ) {
+        $filter = ['sku' => $product->getSku() . '-1'];
+        $productGrid->open()->getProductGrid()->searchAndOpen($filter);
+
+        $form = $productPage->getForm();
+        $formData = $form->getData($product);
+        foreach (array_keys($formData['configurable_attributes_data']['matrix']) as $key) {
+            unset($formData['configurable_attributes_data']['matrix'][$key]['price']);
+        }
+
+        $fixtureData = $this->prepareFixtureData($product->getData());
+        $attributes = $fixtureData['configurable_attributes_data']['attributes_data'];
+        $matrix = $fixtureData['configurable_attributes_data']['matrix'];
+        unset($fixtureData['configurable_attributes_data']);
+
+        $fixtureData['configurable_attributes_data']['attributes_data'] = $this->prepareAttributes($attributes);
+        $fixtureData['configurable_attributes_data']['matrix'] = $this->prepareMatrix($matrix);
+
+        $errors = $this->verifyData($fixtureData, $formData);
+        \PHPUnit_Framework_Assert::assertEmpty($errors, $errors);
+    }
+
+    /**
+     * Preparing data attributes fixture
+     *
+     * @param array $fixtureAttribute
+     * @return array
+     */
+    protected function prepareAttributes(array $fixtureAttribute)
+    {
+        foreach ($fixtureAttribute as &$attribute) {
+            unset($attribute['id'], $attribute['label'], $attribute['code']);
+            foreach ($attribute['options'] as &$option) {
+                $option['pricing_value'] = number_format($option['pricing_value'], 4);
+                unset($option['id']);
+            }
+        }
+
+        return $fixtureAttribute;
+    }
+
+    /**
+     * Preparing data matrix fixture
+     *
+     * @param array $fixtureMatrix
+     * @return array
+     */
+    protected function prepareMatrix(array $fixtureMatrix)
+    {
+        foreach ($fixtureMatrix as &$matrix) {
+            $matrix['display'] = 'Yes';
+            unset($matrix['configurable_attribute'], $matrix['associated_product_ids']);
+        }
+
+        return $fixtureMatrix;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable.php
index f985d2fe282702e26467e3a880c56b70e604a434..927a42c2111f2aa1709c0087ddff2598fc8ea2f7 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable.php
@@ -591,7 +591,8 @@ class CatalogProductConfigurable extends InjectableFixture
     protected $website_ids = [
         'attribute_code' => 'website_ids',
         'backend_type' => 'virtual',
-        'default_value' => 'Main Website',
+        'default_value' => ['Main Website'],
+        'group' => 'websites',
     ];
 
     public function getCategoryIds()
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable.xml
index b37c96cd976cc7c19d1068794eac7499806f5bad..8fcbbdc441bacdff88b78a43f3f23b2ed290443e 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable.xml
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable.xml
@@ -452,6 +452,7 @@
             <attribute_code>website_ids</attribute_code>
             <backend_type>virtual</backend_type>
             <default_value>Main Website</default_value>
+            <group>websites</group>
         </website_ids>
     </fields>
     <data_set>
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/ConfigurableAttributesData.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/ConfigurableAttributesData.php
index 0e9beb70f817bd6b82c13757d07c9ab61e5b49ba..bbcc25bee46541bc73b0d382e1cd78693d7591a6 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/ConfigurableAttributesData.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/ConfigurableAttributesData.php
@@ -444,7 +444,8 @@ class ConfigurableAttributesData implements FixtureInterface
                         'name' => 'In configurable %isolation% %attribute_0-option_0_name% %attribute_1-option_1_name%',
                         'sku' => 'sku_configurable_%isolation%_%attribute_0-option_0_id%_%attribute_1-option_1_id%',
                         'qty' => 10,
-                        'weight' => 1
+                        'weight' => 1,
+                        'options_names' => []
                     ],
                     '%attribute_0-option_0%-%attribute_1-option_2%' => [
                         'configurable_attribute' => [
@@ -455,7 +456,8 @@ class ConfigurableAttributesData implements FixtureInterface
                         'name' => 'In configurable %isolation% %attribute_0-option_0_name% %attribute_1-option_2_name%',
                         'sku' => 'sku_configurable_%isolation%_%attribute_0-option_0_id%_%attribute_1-option_2_id%',
                         'qty' => 10,
-                        'weight' => 1
+                        'weight' => 1,
+                        'options_names' => []
                     ],
                     '%attribute_0-option_1%-%attribute_1-option_0%' => [
                         'configurable_attribute' => [
@@ -466,7 +468,8 @@ class ConfigurableAttributesData implements FixtureInterface
                         'name' => 'In configurable %isolation% %attribute_0-option_1_name% %attribute_1-option_0_name%',
                         'sku' => 'sku_configurable_%isolation%_%attribute_0-option_1_id%_%attribute_1-option_0_id%',
                         'qty' => 10,
-                        'weight' => 1
+                        'weight' => 1,
+                        'options_names' => []
                     ],
                     '%attribute_0-option_1%-%attribute_1-option_1%' => [
                         'configurable_attribute' => [
@@ -477,7 +480,8 @@ class ConfigurableAttributesData implements FixtureInterface
                         'name' => 'In configurable %isolation% %attribute_0-option_1_name% %attribute_1-option_1_name%',
                         'sku' => 'sku_configurable_%isolation%_%attribute_0-option_1_id%_%attribute_1-option_1_id%',
                         'qty' => 10,
-                        'weight' => 1
+                        'weight' => 1,
+                        'options_names' => []
                     ],
                     '%attribute_0-option_1%-%attribute_1-option_2%' => [
                         'configurable_attribute' => [
@@ -488,7 +492,8 @@ class ConfigurableAttributesData implements FixtureInterface
                         'name' => 'In configurable %isolation% %attribute_0-option_1_name% %attribute_1-option_2_name%',
                         'sku' => 'sku_configurable_%isolation%_%attribute_0-option_1_id%_%attribute_1-option_2_id%',
                         'qty' => 10,
-                        'weight' => 1
+                        'weight' => 1,
+                        'options_names' => []
                     ],
                     '%attribute_0-option_2%-%attribute_1-option_0%' => [
                         'configurable_attribute' => [
@@ -499,7 +504,8 @@ class ConfigurableAttributesData implements FixtureInterface
                         'name' => 'In configurable %isolation% %attribute_0-option_2_name% %attribute_1-option_0_name%',
                         'sku' => 'sku_configurable_%isolation%_%attribute_0-option_2_id%_%attribute_1-option_0_id%',
                         'qty' => 10,
-                        'weight' => 1
+                        'weight' => 1,
+                        'options_names' => []
                     ],
                     '%attribute_0-option_2%-%attribute_1-option_1%' => [
                         'configurable_attribute' => [
@@ -510,7 +516,8 @@ class ConfigurableAttributesData implements FixtureInterface
                         'name' => 'In configurable %isolation% %attribute_0-option_2_name% %attribute_1-option_1_name%',
                         'sku' => 'sku_configurable_%isolation%_%attribute_0-option_2_id%_%attribute_1-option_1_id%',
                         'qty' => 10,
-                        'weight' => 1
+                        'weight' => 1,
+                        'options_names' => []
                     ],
                     '%attribute_0-option_2%-%attribute_1-option_2%' => [
                         'configurable_attribute' => [
@@ -521,7 +528,8 @@ class ConfigurableAttributesData implements FixtureInterface
                         'name' => 'In configurable %isolation% %attribute_0-option_2_name% %attribute_1-option_2_name%',
                         'sku' => 'sku_configurable_%isolation%_%attribute_0-option_2_id%_%attribute_1-option_2_id%',
                         'qty' => 10,
-                        'weight' => 1
+                        'weight' => 1,
+                        'options_names' => []
                     ]
                 ]
             ],
@@ -557,7 +565,8 @@ class ConfigurableAttributesData implements FixtureInterface
                         'name' => 'In configurable %isolation% %attribute_0-option_0_name%',
                         'sku' => 'sku_configurable_%isolation%_%attribute_0-option_0_id%',
                         'qty' => 10,
-                        'weight' => 1
+                        'weight' => 1,
+                        'options_names' => []
                     ]
                 ]
             ]
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/CatalogProductEdit.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/CatalogProductEdit.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ae766e3884c949848d0e293ce0ffe7f7af6439e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/CatalogProductEdit.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\ConfigurableProduct\Test\Page\Adminhtml;
+
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit as ParentCatalogProductEdit;
+
+/**
+ * Class CatalogProductEdit
+ */
+class CatalogProductEdit extends ParentCatalogProductEdit
+{
+    const MCA = 'configurable/catalog/product/edit';
+
+    /**
+     * Custom constructor
+     */
+    protected function _init()
+    {
+        $this->_blocks['form'] = [
+            'name' => 'form',
+            'class' => 'Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\ProductForm',
+            'locator' => '[id="page:main-container"]',
+            'strategy' => 'css selector',
+        ];
+    }
+
+    /**
+     * @return \Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\ProductForm
+     */
+    public function getForm()
+    {
+        return $this->getBlockInstance('form');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/CatalogProductEdit.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/CatalogProductEdit.xml
new file mode 100644
index 0000000000000000000000000000000000000000..833ae1e11ce3056af7ff0e06afeacb9fcc723db8
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/CatalogProductEdit.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<page mca="configurable/catalog/product/edit" >
+    <block>
+        <name>form</name>
+        <class>Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\ProductForm</class>
+        <locator>[id="page:main-container"]</locator>
+        <strategy>css selector</strategy>
+    </block>
+</page>
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/CatalogProductNew.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/CatalogProductNew.php
index 42e4d61f36090653918feafbb746faf7981fd803..d07ee53638df4624af6cbad3bc99a76ad32fb051 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/CatalogProductNew.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/CatalogProductNew.php
@@ -32,7 +32,8 @@ use Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew as ParentCatalogProduc
  */
 class CatalogProductNew extends ParentCatalogProductNew
 {
-    const MCA = 'catalog/product_configurable/new';
+    const MCA = 'configurable/catalog/product/new';
+
     /**
      * Custom constructor
      */
@@ -44,7 +45,6 @@ class CatalogProductNew extends ParentCatalogProductNew
             'locator' => '[id="page:main-container"]',
             'strategy' => 'css selector',
         ];
-        $this->_url = $_ENV['app_backend_url'] . static::MCA;
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/CatalogProductNew.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/CatalogProductNew.xml
index f15ec3f97606bfc89b73e7e46503462674159edf..eccfc8eebdaa50d198f4714613f9a30f3aa23927 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/CatalogProductNew.xml
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/CatalogProductNew.xml
@@ -23,7 +23,7 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 -->
-<page mca="catalog/product_configurable/new">
+<page mca="configurable/catalog/product/new">
     <block>
         <name>form</name>
         <class>Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\ProductForm</class>
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/Product/CreateConfigurableEntityTest.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/Product/CreateConfigurableEntityTest.php
old mode 100644
new mode 100755
index dc214e17b828d97b06fef6ee9213a3c15bd66698..05581120708e14808d0983bc37d42f4d019fa09b
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/Product/CreateConfigurableEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/Product/CreateConfigurableEntityTest.php
@@ -109,10 +109,10 @@ class CreateConfigurableEntityTest extends Injectable
     {
         // Steps
         $this->productPageGrid->open();
-        $this->productPageGrid->getProductBlock()->addProduct('configurable');
+        $this->productPageGrid->getGridPageActionBlock()->addProduct('configurable');
         // Fill form
         $productBlockForm = $this->newProductPage->getConfigurableProductForm();
-        $productBlockForm->fillProduct($configurable, $category);
+        $productBlockForm->fill($configurable, null, $category);
         $this->newProductPage->getFormAction()->saveProduct($this->newProductPage, $configurable);
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/Product/CreateConfigurableEntityTest/testCreate.csv b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/Product/CreateConfigurableEntityTest/testCreate.csv
old mode 100644
new mode 100755
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/global/constraint.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/global/constraint.xml
index a377726694e2e22cb6e8c3cd335f0ef683daa758..c480d4f9194f825ee349754c8601fff750b633ba 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/global/constraint.xml
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/global/constraint.xml
@@ -63,4 +63,12 @@
             <newProductPage class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew" />
         </require>
     </assertProductAttributeIsConfigurable>
+    <assertProductConfigurableDuplicateForm module="Magento_ConfigurableProduct">
+        <severeness>high</severeness>
+        <require>
+            <productGrid class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex" />
+            <productPage class="Magento\ConfigurableProduct\Test\Page\Adminhtml\CatalogProductEdit" />
+            <product class="Mtf\Fixture\FixtureInterface" />
+        </require>
+    </assertProductConfigurableDuplicateForm>
 </constraint>
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/Block/Adminhtml/System/Variable/FormPageActions.php b/dev/tests/functional/tests/app/Magento/Core/Test/Block/Adminhtml/System/Variable/FormPageActions.php
new file mode 100644
index 0000000000000000000000000000000000000000..9386d490f9c66b1918d6848e81b80aa04cff8646
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/Block/Adminhtml/System/Variable/FormPageActions.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Core\Test\Block\Adminhtml\System\Variable;
+
+use Magento\Backend\Test\Block\FormPageActions as AbstractFormPageActions;
+use Mtf\Client\Element\Locator;
+
+/**
+ * Class FormPageActions
+ * Page Actions for Custom Variable
+ */
+class FormPageActions extends AbstractFormPageActions
+{
+    /**
+     * "Save and Continue Edit" button
+     *
+     * @var string
+     */
+    protected $saveAndContinueButton = '#save_and_edit';
+
+    /**
+     * Store View button
+     *
+     * @var string
+     */
+    protected $storeViewButton = '.store-switcher [data-toggle="dropdown"]';
+
+    /**
+     * Store View locator
+     *
+     * @var string
+     */
+    protected $storeView = './/*/a[contains(text(),"%s")]';
+
+    /**
+     * Select Store View
+     *
+     * @param string $storeName
+     * @throws \Exception
+     * @return void
+     */
+    public function selectStoreView($storeName)
+    {
+        $this->_rootElement->find($this->storeViewButton)->click();
+        $selector = sprintf($this->storeView, $storeName);
+        if ($this->_rootElement->find($selector, Locator::SELECTOR_XPATH)->isVisible()) {
+            $this->_rootElement->find($selector, Locator::SELECTOR_XPATH)->click();
+        } else {
+            throw new \Exception('Store View with name \'' . $storeName . '\' is not visible!');
+        }
+        $this->_rootElement->acceptAlert();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableForm.php b/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..be548d5a94520ba8087057a90c6e6b626d39ea4c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableForm.php
@@ -0,0 +1,115 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Core\Test\Constraint;
+
+use Magento\Store\Test\Fixture\Store;
+use Mtf\Constraint\AbstractAssertForm;
+use Magento\Core\Test\Fixture\SystemVariable;
+use Magento\Core\Test\Page\Adminhtml\SystemVariableIndex;
+use Magento\Core\Test\Page\Adminhtml\SystemVariableNew;
+
+/**
+ * Class AssertCustomVariableForm
+ * Check that data at the form corresponds to the fixture data
+ */
+class AssertCustomVariableForm extends AbstractAssertForm
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Skipped fields for verify data
+     *
+     * @var array
+     */
+    protected $skippedFields = ['use_default_value', 'variable_id'];
+
+    /**
+     * Assert that data at the form corresponds to the fixture data
+     *
+     * @param SystemVariable $customVariable
+     * @param SystemVariableIndex $systemVariableIndex
+     * @param SystemVariableNew $systemVariableNew
+     * @param Store $storeOrigin
+     * @param SystemVariable $customVariableOrigin
+     * @return void
+     *
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     */
+    public function processAssert(
+        SystemVariable $customVariable,
+        SystemVariableIndex $systemVariableIndex,
+        SystemVariableNew $systemVariableNew,
+        Store $storeOrigin = null,
+        SystemVariable $customVariableOrigin = null
+    ) {
+        // Prepare data
+        $data = ($customVariableOrigin === null)
+            ? $customVariable->getData()
+            : array_merge($customVariableOrigin->getData(), $customVariable->getData());
+        if ($customVariableOrigin !== null) {
+            $dataOrigin = $data;
+            $dataOrigin['html_value'] = $customVariableOrigin->getHtmlValue();
+            $dataOrigin['plain_value'] = $customVariableOrigin->getPlainValue();
+        } else {
+            $dataOrigin = $data;
+        }
+        if ($data['html_value'] == '') {
+            $data['html_value'] = $customVariableOrigin->getHtmlValue();
+            $data['use_default_value'] = 'Yes';
+        }
+        $data['plain_value'] = ($data['plain_value'] == '')
+            ? $customVariableOrigin->getPlainValue()
+            : $data['plain_value'];
+        // Perform assert
+        $systemVariableIndex->open();
+        $systemVariableIndex->getSystemVariableGrid()->searchAndOpen(['code' => $data['code']]);
+
+        $formData = $systemVariableNew->getSystemVariableForm()->getData($customVariable);
+        $errors = $this->verifyData($dataOrigin, $formData);
+        \PHPUnit_Framework_Assert::assertEmpty($errors, $errors);
+
+        if ($storeOrigin !== null) {
+            $systemVariableNew->getFormPageActions()->selectStoreView($storeOrigin->getName());
+            $formData = $systemVariableNew->getSystemVariableForm()->getData($customVariable);
+            $errors = $this->verifyData($data, $formData);
+            \PHPUnit_Framework_Assert::assertEmpty($errors, $errors);
+        }
+    }
+
+    /**
+     * Text success verify Custom Variable
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Displayed Custom Variable data on edit page(backend) equals to passed from fixture.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableInGrid.php b/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableInGrid.php
new file mode 100644
index 0000000000000000000000000000000000000000..07feab08926c6974372fe25cfd52c9078aae8a4c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableInGrid.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Core\Test\Constraint;
+
+use Magento\Core\Test\Fixture\SystemVariable;
+use Magento\Core\Test\Page\Adminhtml\SystemVariableIndex;
+use Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Class AssertCustomVariableInGrid
+ * Check that created custom variable is displayed on backend in custom variable grid and has correct data
+ * according to dataset
+ */
+class AssertCustomVariableInGrid extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert custom variable is displayed on backend in custom variable grid
+     *
+     * @param SystemVariableIndex $systemVariableIndexNew
+     * @param SystemVariable $customVariable
+     * @return void
+     */
+    public function processAssert(
+        SystemVariableIndex $systemVariableIndexNew,
+        SystemVariable $customVariable
+    ) {
+        $filter = [
+            'code' => $customVariable->getCode(),
+            'name' => $customVariable->getName(),
+        ];
+
+        $systemVariableIndexNew->open();
+        \PHPUnit_Framework_Assert::assertTrue(
+            $systemVariableIndexNew->getSystemVariableGrid()->isRowVisible($filter),
+            'Custom Variable with code \'' . $filter['code'] . '\' is absent in Custom Variable grid.'
+        );
+    }
+
+    /**
+     * Returns a string representation of successful assertion
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Custom System Variable is present in grid.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableInPage.php b/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableInPage.php
new file mode 100644
index 0000000000000000000000000000000000000000..e844c3e1d1c6cac66cf5932adb4d325d0380c1d4
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableInPage.php
@@ -0,0 +1,149 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Core\Test\Constraint;
+
+use Mtf\Client\Browser;
+use Mtf\Fixture\FixtureFactory;
+use Magento\Cms\Test\Page\CmsIndex;
+use Magento\Store\Test\Fixture\Store;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Core\Test\Fixture\SystemVariable;
+
+/**
+ * Class AssertCustomVariableInPage
+ */
+class AssertCustomVariableInPage extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Add created variable to page and assert that Custom Variable is displayed on frontend page and has
+     * correct data according to dataset.
+     *
+     * @param SystemVariable $customVariable
+     * @param CmsIndex $cmsIndex
+     * @param SystemVariable $variable
+     * @param FixtureFactory $fixtureFactory
+     * @param Browser $browser
+     * @param Store $storeOrigin
+     * @param SystemVariable $customVariableOrigin
+     * @return void
+     */
+    public function processAssert(
+        SystemVariable $customVariable,
+        CmsIndex $cmsIndex,
+        SystemVariable $variable,
+        FixtureFactory $fixtureFactory,
+        Browser $browser,
+        Store $storeOrigin = null,
+        SystemVariable $customVariableOrigin = null
+    ) {
+        $cmsPage = $fixtureFactory->createByCode(
+            'cmsPage',
+            [
+                'dataSet' => 'default',
+                'data' => ['content' => '{{customVar code=' . $customVariable->getCode() . '}}'],
+            ]
+        );
+        $cmsPage->persist();
+        $url = $_ENV['app_frontend_url'] . $cmsPage->getIdentifier();
+        $browser->open($url);
+
+        $cmsIndex->getStoreSwitcherBlock()->selectStoreView('Default Store View');
+
+        $htmlValue = ($customVariableOrigin !== null)
+            ? $this->getHtmlValue($customVariable, $customVariableOrigin)
+            : strip_tags($customVariable->getHtmlValue());
+        $pageContent = $cmsIndex->getMainContentBlock()->getPageContent();
+        $this->checkVariable($htmlValue, $pageContent);
+
+        if ($storeOrigin !== null) {
+            $cmsIndex->getStoreSwitcherBlock()->selectStoreView($storeOrigin->getName());
+            $htmlValue = strip_tags($customVariable->getHtmlValue());
+            if ($htmlValue === '') {
+                $htmlValue = strip_tags($variable->getHtmlValue());
+            }
+            $pageContent = $cmsIndex->getMainContentBlock()->getPageContent();
+            $this->checkVariable($htmlValue, $pageContent);
+        }
+    }
+
+    /**
+     * Get html value
+     *
+     * @param SystemVariable $customVariable
+     * @param SystemVariable $customVariableOrigin
+     * @return string
+     */
+    protected function getHtmlValue(SystemVariable $customVariable, SystemVariable $customVariableOrigin)
+    {
+        $data = array_merge($customVariableOrigin->getData(), $customVariable->getData());
+        if ($customVariable->getHtmlValue() == "" && $customVariableOrigin->getHtmlValue() == "") {
+            $htmlValue = ($data['plain_value'] == "")
+                ? $customVariableOrigin->getPlainValue()
+                : $data['plain_value'];
+        } else {
+            $htmlValue = ($customVariableOrigin == null)
+                ? $customVariable->getHtmlValue()
+                : $customVariableOrigin->getHtmlValue();
+            $htmlValue = strip_tags($htmlValue);
+        }
+        return $htmlValue;
+    }
+
+    /**
+     * Check Variable on frontend page
+     *
+     * @param string $htmlValue
+     * @param string $pageContent
+     * @return void
+     */
+    protected function checkVariable($htmlValue, $pageContent)
+    {
+        \PHPUnit_Framework_Assert::assertEquals(
+            $htmlValue,
+            $pageContent,
+            'Wrong content is displayed on frontend page'
+            . "\nExpected: " . $htmlValue
+            . "\nActual: " . $pageContent
+        );
+
+    }
+
+    /**
+     * Returns a string representation of successful assertion
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Custom Variable is displayed on frontend page';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertSystemVariableNotInCmsPageForm.php b/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableNotInCmsPageForm.php
similarity index 95%
rename from dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertSystemVariableNotInCmsPageForm.php
rename to dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableNotInCmsPageForm.php
index 85ffc1b1ff4ebc6c8396f50dd2a05686bb53e646..f85e03689ad66f9882ffce00aae76ef19276ab69 100644
--- a/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertSystemVariableNotInCmsPageForm.php
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableNotInCmsPageForm.php
@@ -29,9 +29,9 @@ use Magento\Core\Test\Fixture\SystemVariable;
 use Mtf\Constraint\AbstractConstraint;
 
 /**
- * Class AssertSystemVariableNotInCmsPageForm
+ * Class AssertCustomVariableNotInCmsPageForm
  */
-class AssertSystemVariableNotInCmsPageForm extends AbstractConstraint
+class AssertCustomVariableNotInCmsPageForm extends AbstractConstraint
 {
     /**
      * Constraint severeness
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertSystemVariableNotInGrid.php b/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableNotInGrid.php
similarity index 95%
rename from dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertSystemVariableNotInGrid.php
rename to dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableNotInGrid.php
index a8f89116f609881c56a297c335afabef573b3c4c..98d4de322b17c6cd07ea67e00f59efa9c0ff7700 100644
--- a/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertSystemVariableNotInGrid.php
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableNotInGrid.php
@@ -29,9 +29,9 @@ use Magento\Core\Test\Page\Adminhtml\SystemVariableIndex;
 use Mtf\Constraint\AbstractConstraint;
 
 /**
- * Class AssertSystemVariableNotInGrid
+ * Class AssertCustomVariableNotInGrid
  */
-class AssertSystemVariableNotInGrid extends AbstractConstraint
+class AssertCustomVariableNotInGrid extends AbstractConstraint
 {
     /**
      * Constraint severeness
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertSystemVariableSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableSuccessDeleteMessage.php
similarity index 94%
rename from dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertSystemVariableSuccessDeleteMessage.php
rename to dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableSuccessDeleteMessage.php
index 3c5d294676d44294ec5d27dff6848864c3a43623..bc0c05a0eeba3f084801e1bf38feaf6789587877 100644
--- a/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertSystemVariableSuccessDeleteMessage.php
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableSuccessDeleteMessage.php
@@ -28,9 +28,9 @@ use Magento\Core\Test\Page\Adminhtml\SystemVariableIndex;
 use Mtf\Constraint\AbstractConstraint;
 
 /**
- * Class AssertSystemVariableSuccessDeleteMessage
+ * Class AssertCustomVariableSuccessDeleteMessage
  */
-class AssertSystemVariableSuccessDeleteMessage extends AbstractConstraint
+class AssertCustomVariableSuccessDeleteMessage extends AbstractConstraint
 {
     const SUCCESS_DELETE_MESSAGE = 'You deleted the custom variable.';
 
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableSuccessSaveMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..33e535e26d55c1b4cfd338d9cbff33a5754a3608
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/Constraint/AssertCustomVariableSuccessSaveMessage.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Core\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Core\Test\Page\Adminhtml\SystemVariableIndex;
+
+/**
+ * Class AssertCustomVariableSuccessSaveMessage
+ * Check success delete message is correct after Custom System Variable deleted
+ */
+class AssertCustomVariableSuccessSaveMessage extends AbstractConstraint
+{
+    const SUCCESS_SAVE_MESSAGE = 'You saved the custom variable.';
+
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert that success delete message is correct after Custom System Variable deleted
+     *
+     * @param SystemVariableIndex $systemVariableIndexPage
+     * @return void
+     */
+    public function processAssert(SystemVariableIndex $systemVariableIndexPage)
+    {
+        $actualMessage = $systemVariableIndexPage->getMessagesBlock()->getSuccessMessages();
+        \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 successful assertion
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Custom Variable success save message is correct.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/Page/Adminhtml/SystemVariableNew.php b/dev/tests/functional/tests/app/Magento/Core/Test/Page/Adminhtml/SystemVariableNew.php
index df051f7158a5f6af7e98427913c3f9229b4d3078..3dfcc11c43dfc28493a3ba5222035d72bc21f79c 100644
--- a/dev/tests/functional/tests/app/Magento/Core/Test/Page/Adminhtml/SystemVariableNew.php
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/Page/Adminhtml/SystemVariableNew.php
@@ -36,7 +36,7 @@ class SystemVariableNew extends BackendPage
     protected $_blocks = [
         'formPageActions' => [
             'name' => 'formPageActions',
-            'class' => 'Magento\Backend\Test\Block\FormPageActions',
+            'class' => 'Magento\Core\Test\Block\Adminhtml\System\Variable\FormPageActions',
             'locator' => '.page-main-actions',
             'strategy' => 'css selector',
         ],
@@ -49,7 +49,7 @@ class SystemVariableNew extends BackendPage
     ];
 
     /**
-     * @return \Magento\Backend\Test\Block\FormPageActions
+     * @return \Magento\Core\Test\Block\Adminhtml\System\Variable\FormPageActions
      */
     public function getFormPageActions()
     {
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/Page/Adminhtml/SystemVariableNew.xml b/dev/tests/functional/tests/app/Magento/Core/Test/Page/Adminhtml/SystemVariableNew.xml
index a2dac6b6b79862c0016b634971b5f56acbe310c9..014bcf2f2dedb57881398364ffe3d68620aeee38 100644
--- a/dev/tests/functional/tests/app/Magento/Core/Test/Page/Adminhtml/SystemVariableNew.xml
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/Page/Adminhtml/SystemVariableNew.xml
@@ -26,7 +26,7 @@
 <page mca="admin/system_variable/new" >
     <block>
         <name>formPageActions</name>
-        <class>Magento\Backend\Test\Block\FormPageActions</class>
+        <class>Magento\Core\Test\Block\Adminhtml\System\Variable\FormPageActions</class>
         <locator>.page-main-actions</locator>
         <strategy>css selector</strategy>
     </block>
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/CreateCustomVariableEntityTest.php b/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/CreateCustomVariableEntityTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7f70a832a6f887fde4c7d26e898952e019847739
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/CreateCustomVariableEntityTest.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Core\Test\TestCase;
+
+use Mtf\TestCase\Injectable;
+use Magento\Core\Test\Fixture\SystemVariable;
+use Magento\Core\Test\Page\Adminhtml\SystemVariableIndex;
+use Magento\Core\Test\Page\Adminhtml\SystemVariableNew;
+
+/**
+ * Test Creation for CreateCustomVariableEntity
+ *
+ * Test Flow:
+ * Steps:
+ * 1. Login to backend.
+ * 2. Navigate to System->Other Settings->Custom Variables.
+ * 3. Click on 'Add new variable' button.
+ * 4. Fill in all data according to data set.
+ * 5. Click 'Save' button.
+ * 6. Perform all asserts.
+ *
+ * @group Variables_(PS)
+ * @ZephyrId MAGETWO-23293
+ */
+class CreateCustomVariableEntityTest extends Injectable
+{
+    /**
+     * Custom System Variable grid page
+     *
+     * @var SystemVariableIndex
+     */
+    protected $systemVariableIndexPage;
+
+    /**
+     * Custom System Variable new and edit page
+     *
+     * @var SystemVariableNew
+     */
+    protected $systemVariableNewPage;
+
+    /**
+     * Injection data
+     *
+     * @param SystemVariableIndex $systemVariableIndex
+     * @param SystemVariableNew $systemVariableNew
+     * @return void
+     */
+    public function __inject(
+        SystemVariableIndex $systemVariableIndex,
+        SystemVariableNew $systemVariableNew
+    ) {
+        $this->systemVariableIndexPage = $systemVariableIndex;
+        $this->systemVariableNewPage = $systemVariableNew;
+    }
+
+    /**
+     * Delete Custom System Variable Entity test
+     *
+     * @param SystemVariable $customVariable
+     * @return void
+     */
+    public function test(SystemVariable $customVariable)
+    {
+        // Steps
+        $this->systemVariableIndexPage->open();
+        $this->systemVariableIndexPage->getGridPageActions()->addNew();
+        $this->systemVariableNewPage->getSystemVariableForm()->fill($customVariable);
+        $this->systemVariableNewPage->getFormPageActions()->save();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/CreateCustomVariableEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/CreateCustomVariableEntityTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..6808d297faf51ee134f04cea89b2684e071d1314
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/CreateCustomVariableEntityTest/test.csv
@@ -0,0 +1,3 @@
+"customVariable/data/code";"customVariable/data/name";"customVariable/data/html_value";"customVariable/data/plain_value";"constraint"
+"variableCode%isolation%";"variableName%isolation%";"<h1>variableName%isolation%</h1>";"<p>variablePlainText%isolation%</p>";"assertCustomVariableSuccessSaveMessage, assertCustomVariableInGrid, assertCustomVariableForm, assertCustomVariableInPage"
+"variableCode%isolation%";"variableName%isolation%";"<p>variableName%isolation%</p>";"variablePlainText%isolation%";"assertCustomVariableSuccessSaveMessage, assertCustomVariableInGrid, assertCustomVariableForm, assertCustomVariableInPage"
\ No newline at end of file
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/DeleteSystemVariableEntityTest.php b/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/DeleteCustomVariableEntityTest.php
similarity index 96%
rename from dev/tests/functional/tests/app/Magento/Core/Test/TestCase/DeleteSystemVariableEntityTest.php
rename to dev/tests/functional/tests/app/Magento/Core/Test/TestCase/DeleteCustomVariableEntityTest.php
index 45623cb81a7258a5a750ee0a18649f48f825baa4..5688063bbb5b660d16609885020b4516dedb1ca7 100644
--- a/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/DeleteSystemVariableEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/DeleteCustomVariableEntityTest.php
@@ -31,7 +31,7 @@ use Mtf\Fixture\FixtureFactory;
 use Mtf\TestCase\Injectable;
 
 /**
- * Test Creation for DeleteSystemVariableEntity
+ * Test Creation for DeleteCustomVariableEntityTest
  *
  * Test Flow:
  * Preconditions:
@@ -47,7 +47,7 @@ use Mtf\TestCase\Injectable;
  * @group Variables_(PS)
  * @ZephyrId MAGETWO-25535
  */
-class DeleteSystemVariableEntityTest extends Injectable
+class DeleteCustomVariableEntityTest extends Injectable
 {
     /**
      * Custom System Variable grid page
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/DeleteCustomVariableEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/DeleteCustomVariableEntityTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..250384c701b4c52ae0ded9209d77e3103d58d8bb
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/DeleteCustomVariableEntityTest/test.csv
@@ -0,0 +1,2 @@
+"constraint"
+"assertCustomVariableSuccessDeleteMessage, assertCustomVariableNotInGrid, assertCustomVariableNotInCmsPageForm"
\ No newline at end of file
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/DeleteSystemVariableEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/DeleteSystemVariableEntityTest/test.csv
deleted file mode 100644
index ec58eb1c03c37c8e376808908bf5a05ddc013dad..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/DeleteSystemVariableEntityTest/test.csv
+++ /dev/null
@@ -1,2 +0,0 @@
-"constraint"
-"assertSystemVariableSuccessDeleteMessage, assertSystemVariableNotInGrid, assertSystemVariableNotInCmsPageForm"
\ No newline at end of file
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/UpdateCustomVariableEntityTest.php b/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/UpdateCustomVariableEntityTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1dc357b9fa9fd8d869f1325ea6e723c985b5ea8d
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/UpdateCustomVariableEntityTest.php
@@ -0,0 +1,158 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Core\Test\TestCase;
+
+use Mtf\ObjectManager;
+use Mtf\TestCase\Injectable;
+use Magento\Store\Test\Fixture\Store;
+use Magento\Core\Test\Fixture\SystemVariable;
+use Magento\Core\Test\Page\Adminhtml\SystemVariableNew;
+use Magento\Core\Test\Page\Adminhtml\SystemVariableIndex;
+
+/**
+ * Test Creation for CreateCustomVariableEntity
+ *
+ * Test Flow:
+ * Preconditions:
+ * 1. Custom system variable is created.
+ * 2. Additional Non Default Storeview is created.
+ *
+ * Steps:
+ * 1. Login to backend.
+ * 2. Navigate to System->Other Settings->Custom Variables.
+ * 3. Open from grid created custom system variable.
+ * 4. Navigate to the Store Switcher.
+ * 5. Choose Appropriate Storeview (non default).
+ * 6. Set Use Default Variable Values.
+ * 7. Edit necessary fields.
+ * 8. Save Custom variable using correspond saveActions.
+ * 9. Perform all assertions.
+ *
+ * @group Variables_(PS)
+ * @ZephyrId MAGETWO-26241
+ */
+class UpdateCustomVariableEntityTest extends Injectable
+{
+    /**
+     * Custom System Variable grid page
+     *
+     * @var SystemVariableIndex
+     */
+    protected $systemVariableIndexPage;
+
+    /**
+     * Custom System Variable new and edit page
+     *
+     * @var SystemVariableNew
+     */
+    protected $systemVariableNewPage;
+
+    /**
+     * Store Name
+     *
+     * @var array
+     */
+    public static $storeName;
+
+    /**
+     * Prepare data
+     *
+     * @param Store $storeOrigin
+     * @return array
+     */
+    public function __prepare(Store $storeOrigin)
+    {
+        $storeOrigin->persist();
+        self::$storeName = $storeOrigin->getName();
+
+        return ['storeOrigin' => $storeOrigin];
+    }
+
+    /**
+     * Injection data
+     *
+     * @param SystemVariableIndex $systemVariableIndex
+     * @param SystemVariableNew $systemVariableNew
+     * @param SystemVariable $customVariableOrigin
+     * @return array
+     */
+    public function __inject(
+        SystemVariableIndex $systemVariableIndex,
+        SystemVariableNew $systemVariableNew,
+        SystemVariable $customVariableOrigin
+    ) {
+        $this->systemVariableIndexPage = $systemVariableIndex;
+        $this->systemVariableNewPage = $systemVariableNew;
+
+        $customVariableOrigin->persist();
+
+        return ['customVariableOrigin' => $customVariableOrigin];
+    }
+
+    /**
+     * Update Custom System Variable Entity test
+     *
+     * @param SystemVariable $customVariable
+     * @param SystemVariable $customVariableOrigin
+     * @param Store $storeOrigin
+     * @param $saveAction
+     * @return void
+     */
+    public function test(
+        SystemVariable $customVariable,
+        SystemVariable $customVariableOrigin,
+        Store $storeOrigin,
+        $saveAction
+    ) {
+        $filter = [
+            'code' => $customVariableOrigin->getCode(),
+        ];
+
+        // Steps
+        $this->systemVariableIndexPage->open();
+        $this->systemVariableIndexPage->getSystemVariableGrid()->searchAndOpen($filter);
+        $this->systemVariableNewPage->getFormPageActions()->selectStoreView($storeOrigin->getData('name'));
+        $this->systemVariableNewPage->getSystemVariableForm()->fill($customVariable);
+        $this->systemVariableNewPage->getFormPageActions()->$saveAction();
+    }
+
+    /**
+     * Delete Store after test
+     *
+     * @return void
+     */
+    public static function tearDownAfterClass()
+    {
+        $filter['store_title'] = self::$storeName;
+        $storeIndex = ObjectManager::getInstance()->create('Magento\Backend\Test\Page\Adminhtml\StoreIndex');
+        $storeIndex->open();
+        $storeIndex->getStoreGrid()->searchAndOpen($filter);
+        $storeNew = ObjectManager::getInstance()->create('Magento\Backend\Test\Page\Adminhtml\StoreNew');
+        $storeNew->getFormPageActions()->delete();
+        $storeDelete = ObjectManager::getInstance()->create('Magento\Backend\Test\Page\Adminhtml\StoreDelete');
+        $storeDelete->getStoreForm()->fillForm(['create_backup' => 'No']);
+        $storeDelete->getFormPageActions()->delete();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/UpdateCustomVariableEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/UpdateCustomVariableEntityTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..da2cd79dfef66bad7b9d2cadbe90feb83558f664
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/TestCase/UpdateCustomVariableEntityTest/test.csv
@@ -0,0 +1,5 @@
+"customVariable/data/code";"customVariable/data/name";"customVariable/data/use_default_value";"customVariable/data/html_value";"customVariable/data/plain_value";"saveAction";"constraint"
+"variableCode%isolation%";"variableName%isolation%";"No";"<h1>variableName%isolation%</h1>";"";"save";"assertCustomVariableSuccessSaveMessage, assertCustomVariableInGrid, assertCustomVariableForm, assertCustomVariableInPage"
+"variableCode%isolation%";"variableName%isolation%";"No";"";"<p>variablePlainText%isolation%</p>";"saveAndContinue";"assertCustomVariableSuccessSaveMessage, assertCustomVariableInGrid, assertCustomVariableForm, assertCustomVariableInPage"
+"variableCode%isolation%";"variableName%isolation%";"No";"<h1>variableName%isolation%</h1>";"<p>variablePlainText%isolation%</p>";"saveAndContinue";"assertCustomVariableSuccessSaveMessage, assertCustomVariableInGrid, assertCustomVariableForm, assertCustomVariableInPage"
+"variableCode%isolation%";"variableName%isolation%";"No";"<h1>variableName%isolation%</h1>";"<p>variablePlainText%isolation%</p>";"save";"assertCustomVariableSuccessSaveMessage, assertCustomVariableInGrid, assertCustomVariableInPage"
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/etc/curl/di.xml b/dev/tests/functional/tests/app/Magento/Core/Test/etc/curl/di.xml
index 7fb1490cff2005d37ea423e31772c710f5898827..654b1969a56b935ca901a6d084a7a7271c0c7c66 100644
--- a/dev/tests/functional/tests/app/Magento/Core/Test/etc/curl/di.xml
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/etc/curl/di.xml
@@ -25,4 +25,5 @@
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
     <preference for="\Magento\Core\Test\Handler\SystemVariable\SystemVariableInterface" type="\Magento\Core\Test\Handler\SystemVariable\Curl" />
+    <preference for="\Magento\Core\Test\Handler\ConfigData\ConfigDataInterface" type="\Magento\Core\Test\Handler\ConfigData\Curl" />
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/etc/global/constraint.xml b/dev/tests/functional/tests/app/Magento/Core/Test/etc/global/constraint.xml
index ff54ee59660a7f033945d96293f1ba66138f6047..723b85002f691a2e16af3d56dfe863bee6fca1f9 100644
--- a/dev/tests/functional/tests/app/Magento/Core/Test/etc/global/constraint.xml
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/etc/global/constraint.xml
@@ -24,13 +24,31 @@
  */
 -->
 <constraint>
-    <assertSystemVariableSuccessDeleteMessage module="Magento_Core">
+    <assertCustomVariableSuccessDeleteMessage module="Magento_Core">
         <severeness>low</severeness>
-    </assertSystemVariableSuccessDeleteMessage>
-    <assertSystemVariableNotInGrid module="Magento_Core">
+    </assertCustomVariableSuccessDeleteMessage>
+    <assertCustomVariableNotInGrid module="Magento_Core">
         <severeness>low</severeness>
-    </assertSystemVariableNotInGrid>
-    <assertSystemVariableNotInCmsPageForm module="Magento_Core">
+    </assertCustomVariableNotInGrid>
+    <assertCustomVariableNotInCmsPageForm module="Magento_Core">
         <severeness>low</severeness>
-    </assertSystemVariableNotInCmsPageForm>
+    </assertCustomVariableNotInCmsPageForm>
+    <assertCustomVariableSuccessSaveMessage module="Magento_Core">
+        <severeness>low</severeness>
+    </assertCustomVariableSuccessSaveMessage>
+    <assertCustomVariableInGrid module="Magento_Core">
+        <severeness>low</severeness>
+    </assertCustomVariableInGrid>
+    <assertCustomVariableInPageStoreview module="Magento_Core">
+        <severeness>low</severeness>
+    </assertCustomVariableInPageStoreview>
+    <assertCustomVariableNotInCmsPageForm module="Magento_Core">
+        <severeness>low</severeness>
+    </assertCustomVariableNotInCmsPageForm>
+    <assertCustomVariableForm module="Magento_Core">
+        <severeness>low</severeness>
+    </assertCustomVariableForm>
+    <assertCustomVariableInPage module="Magento_Core">
+        <severeness>low</severeness>
+    </assertCustomVariableInPage>
 </constraint>
diff --git a/dev/tests/functional/tests/app/Magento/Core/Test/etc/global/fixture.xml b/dev/tests/functional/tests/app/Magento/Core/Test/etc/global/fixture.xml
index b71f00f7be2a3de3d9b324638e455a1a2709ae1c..81c2b35e314c06a8f80aa24e89ccfa87c0b24fd4 100644
--- a/dev/tests/functional/tests/app/Magento/Core/Test/etc/global/fixture.xml
+++ b/dev/tests/functional/tests/app/Magento/Core/Test/etc/global/fixture.xml
@@ -32,4 +32,16 @@
         </entities>
         <collection>Magento\Core\Model\Resource\Variable\Collection</collection>
     </systemVariable>
+    <configData module="Magento_Core">
+        <module>Magento_Core</module>
+        <type>flat</type>
+        <entity_type>core_config_data</entity_type>
+        <collection>Magento\Core\Model\Resource\Config\Data\Collection</collection>
+        <fields>
+            <section>
+                <attribute_code>section</attribute_code>
+                <backend_type>virtual</backend_type>
+            </section>
+        </fields>
+    </configData>
 </fixture>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Account/Dashboard/Address.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Account/Dashboard/Address.php
index f50b7d565e09563813e745e583d9d31433586382..4ee0087a624343b6356b589f4a71439e863b4f39 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Account/Dashboard/Address.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Account/Dashboard/Address.php
@@ -18,7 +18,6 @@
  * versions in the future. If you wish to customize Magento for your
  * needs please refer to http://www.magentocommerce.com for more information.
  *
- * @spi
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
@@ -28,23 +27,59 @@ namespace Magento\Customer\Test\Block\Account\Dashboard;
 use Mtf\Block\Block;
 
 /**
+ * Class Address
  * Customer Dashboard Address Book block
- *
  */
 class Address extends Block
 {
     /**
-     *  Default Billing Address Edit link
+     * Default Billing Address Edit link
      *
      * @var string
      */
     protected $defaultBillingAddressEdit = '[data-ui-id=default-billing-edit-link]';
 
+    /**
+     * Shipping address block selector
+     *
+     * @var string
+     */
+    protected $shippingAddressBlock = '.shipping address';
+
+    /**
+     * Billing address block selector
+     *
+     * @var string
+     */
+    protected $billingAddressBlock = '.billing address';
+
     /**
      * Edit Default Billing Address
+     *
+     * @return void
      */
     public function editBillingAddress()
     {
         $this->_rootElement->find($this->defaultBillingAddressEdit)->click();
     }
+
+    /**
+     * Returns Default Billing Address Text
+     *
+     * @return array|string
+     */
+    public function getDefaultBillingAddressText()
+    {
+        return $this->_rootElement->find($this->billingAddressBlock)->getText();
+    }
+
+    /**
+     * Returns Default Shipping Address Text
+     *
+     * @return array|string
+     */
+    public function getDefaultShippingAddressText()
+    {
+        return $this->_rootElement->find($this->shippingAddressBlock)->getText();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Account/Dashboard/Info.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Account/Dashboard/Info.php
new file mode 100644
index 0000000000000000000000000000000000000000..8a9b81871bc3148b0cbc7162d1b7ee64fbd1e7f1
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Account/Dashboard/Info.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Customer\Test\Block\Account\Dashboard;
+
+use Mtf\Block\Block;
+
+/**
+ * Class Info
+ * Main block on customer account page
+ */
+class Info extends Block
+{
+    /**
+     * Css selector for Contact Information Edit Link
+     *
+     * @var string
+     */
+    protected $contactInfoEditLink = '.dashboard.info .information a.edit';
+
+    /**
+     * Click on Contact Information Edit Link
+     *
+     * @return void
+     */
+    public function openEditContactInfo()
+    {
+        $this->_rootElement->find($this->contactInfoEditLink)->click();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.php
index 935c115d21153348355be27175e85b6ff468b2ad..e75dfad97e5e6bbcb09ca203178ba8e9616911a5 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.php
@@ -32,7 +32,6 @@ use Magento\Customer\Test\Fixture\Address;
 /**
  * Class Edit
  * Customer address edit block
- *
  */
 class Edit extends Form
 {
@@ -58,7 +57,7 @@ class Edit extends Form
     public function editCustomerAddress(Address $fixture)
     {
         $this->fill($fixture);
-        $this->_rootElement->find($this->saveAddress, Locator::SELECTOR_CSS)->click();
+        $this->saveAddress();
     }
 
     /**
@@ -69,6 +68,16 @@ class Edit extends Form
     public function saveVatID($vat)
     {
         $this->_rootElement->find($this->vatFieldId, Locator::SELECTOR_ID)->setValue($vat);
-        $this->_rootElement->find($this->saveAddress, Locator::SELECTOR_CSS)->click();
+        $this->saveAddress();
+    }
+
+    /**
+     * Click on save address button
+     *
+     * @return void
+     */
+    public function saveAddress()
+    {
+        $this->_rootElement->find($this->saveAddress)->click();
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.xml
index cbd9f0a7f53d234d271635ae98c4a79ed91cd77f..c9445fac697099aee1ed8323a7bad8e2a3f038fc 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.xml
@@ -29,9 +29,9 @@
         <lastname />
         <company />
         <telephone />
-        <street_1>
+        <street>
             <selector>#street_1</selector>
-        </street_1>
+        </street>
         <city />
         <region_id>
             <input>select</input>
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Actions.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php
similarity index 70%
rename from dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Actions.php
rename to dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php
index a877c7b542564763c2822f9fabaa0ad014a90d71..46aa3b0f48b1be6c6203e1c7220b64dbb80e9626 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/System/Store/Actions.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.php
@@ -1,7 +1,5 @@
 <?php
 /**
- * Store actions block
- *
  * Magento
  *
  * NOTICE OF LICENSE
@@ -23,38 +21,37 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Backend\Test\Block\System\Store;
 
-use Mtf\Block\Block;
+namespace Magento\Customer\Test\Block\Form;
+
+use Mtf\Block\Form;
 
-class Actions extends Block
+/**
+ * Class CustomerForm
+ * Customer account edit form
+ */
+class CustomerForm extends Form
 {
     /**
-     * Save button
+     * Save button button css selector
      *
      * @var string
      */
-    protected $saveButton = '#save';
+    protected $saveButton = '[type="submit"]';
 
     /**
-     * Add Store button
+     * Locator for customer attribute on Edit Account Information page
      *
      * @var string
      */
-    protected $addStoreButton = '#add_store';
-
-    /**
-     * Add store
-     */
-    public function addStoreView()
-    {
-        $this->_rootElement->find($this->addStoreButton)->click();
-    }
+    protected $customerAttribute = "[name='%s[]']";
 
     /**
-     * Click "Save" button
+     * Click on save button
+     *
+     * @return void
      */
-    public function clickSave()
+    public function submit()
     {
         $this->_rootElement->find($this->saveButton)->click();
     }
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.xml
new file mode 100644
index 0000000000000000000000000000000000000000..65bf5562f40438d336e6d379d7a5d31528bd766a
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/CustomerForm.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <firstname />
+        <lastname />
+        <email />
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Register.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Register.php
index e49ebe26969aaa3923b59c6c50c4cb238232f070..0fa8b89b81282f997d1f2168788b5c0038b62def 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Register.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Register.php
@@ -31,7 +31,6 @@ use Mtf\Fixture\FixtureInterface;
 /**
  * Class Register
  * Register new customer on Frontend
- *
  */
 class Register extends Form
 {
@@ -42,6 +41,13 @@ class Register extends Form
      */
     protected $submit = '.action.submit';
 
+    /**
+     * Locator for customer attribute on New Order page
+     *
+     * @var string
+     */
+    protected $customerAttribute = "[name='%s']";
+
     /**
      * Create new customer account and fill billing address if it exists
      *
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Register.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Register.xml
index 5809ede11fb8e82b0a2c39e52f11701220dfdb9f..cbef022f1223496f4cc62f5bc3d936d1e742259c 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Register.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Register.xml
@@ -30,9 +30,9 @@
         <email />
         <company />
         <telephone />
-        <street_1>
+        <street>
             <selector>#street_1</selector>
-        </street_1>
+        </street>
         <city />
         <region_id>
             <input>select</input>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerAddressSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerAddressSuccessSaveMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..d23bdd6c0d041f063eb738ca62b45494f58cb2c7
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerAddressSuccessSaveMessage.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Customer\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Customer\Test\Page\CustomerAccountIndex;
+
+/**
+ * Class AssertCustomerAddressSuccessSaveMessage
+ */
+class AssertCustomerAddressSuccessSaveMessage extends AbstractConstraint
+{
+    const SUCCESS_MESSAGE = 'The address has been saved.';
+
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Asserts that success message equals to expected message
+     *
+     * @param CustomerAccountIndex $customerAccountIndex
+     * @return void
+     */
+    public function processAssert(CustomerAccountIndex $customerAccountIndex)
+    {
+        $successMessage = $customerAccountIndex->getMessages()->getSuccessMessages();
+        \PHPUnit_Framework_Assert::assertEquals(
+            self::SUCCESS_MESSAGE,
+            $successMessage,
+            'Wrong success message is displayed.'
+            . "\nExpected: " . self::SUCCESS_MESSAGE
+            . "\nActual: " . $successMessage
+        );
+    }
+
+    /**
+     * Returns success message if equals to expected message
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Success address save message on customer account index page is correct.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerDefaultAddresses.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerDefaultAddresses.php
new file mode 100644
index 0000000000000000000000000000000000000000..5efcb572fd49744c23d31fe20a701acc36156dd2
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerDefaultAddresses.php
@@ -0,0 +1,123 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Customer\Test\Constraint;
+
+use Magento\Customer\Test\Fixture\AddressInjectable;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Customer\Test\Page\CustomerAccountIndex;
+
+/**
+ * Class AssertCustomerDefaultAddresses
+ */
+class AssertCustomerDefaultAddresses extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Asserts that Default Billing Address and Default Shipping Address equal to data from fixture
+     *
+     * @param CustomerAccountIndex $customerAccountIndex
+     * @param AddressInjectable $address
+     * @return void
+     */
+    public function processAssert(CustomerAccountIndex $customerAccountIndex, AddressInjectable $address)
+    {
+        $defaultBillingAddress = explode(
+            "\n",
+            $customerAccountIndex->getDashboardAddress()->getDefaultBillingAddressText()
+        );
+        $defaultShippingAddress = explode(
+            "\n",
+            $customerAccountIndex->getDashboardAddress()->getDefaultShippingAddressText()
+        );
+        $pattern = $this->makeAddressPattern($address);
+        $billingDataDiff = $this->verifyForm($pattern, $defaultBillingAddress);
+        $shippingDataDiff = $this->verifyForm($pattern, $defaultShippingAddress);
+        $dataDiff = array_merge($billingDataDiff, $shippingDataDiff);
+
+        \PHPUnit_Framework_Assert::assertEmpty(
+            $dataDiff,
+            'Billing or shipping form was filled incorrectly.'
+            . "\nLog:\n" . implode(";\n", $dataDiff)
+        );
+    }
+
+    /**
+     * String representation of success assert
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Default billing and shipping address form is correct.';
+    }
+
+    /**
+     * Verifying that form is filled correctly
+     *
+     * @param array $pattern
+     * @param array $address
+     * @return array
+     */
+    protected function verifyForm(array $pattern, array $address)
+    {
+        $errorMessages = [];
+        foreach ($pattern as $key => $value) {
+            if ($value !== $address[$key]) {
+                $errorMessages[] = "Data in fields is not equal."
+                    . "\nExpected: " . $value
+                    . "\nActual: " . $pattern[$key];
+            }
+        }
+        return $errorMessages;
+    }
+
+    /**
+     * Make pattern for form verifying
+     *
+     * @param AddressInjectable $address
+     * @return array
+     */
+    protected function makeAddressPattern(AddressInjectable $address)
+    {
+        $pattern = [];
+        $regionId = $address->getRegionId();
+        $region = $regionId ? $regionId: $address->getRegion();
+
+        $pattern[] = $address->getFirstname() . " " . $address->getLastname();
+        $pattern[] = $address->getCompany();
+        $pattern[] = $address->getStreet();
+        $pattern[] = $address->getCity() . ", " . $region . ", " . $address->getPostcode();
+        $pattern[] = $address->getCountryId();
+        $pattern[] = "T: " . $address->getTelephone();
+        $pattern[] = "F: " . $address->getFax();
+        return $pattern;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerInfoSuccessSavedMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerInfoSuccessSavedMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..2dce65abd7328eb8ab71cae34ac35a0aafb8e4ac
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerInfoSuccessSavedMessage.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Customer\Test\Constraint;
+
+use Magento\Customer\Test\Page\CustomerAccountIndex;
+use Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Class AssertCustomerInfoSuccessSavedMessage
+ */
+class AssertCustomerInfoSuccessSavedMessage extends AbstractConstraint
+{
+    const SUCCESS_MESSAGE = 'The account information has been saved.';
+
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Asserts that success message equals to expected message
+     *
+     * @param CustomerAccountIndex $customerAccountIndex
+     * @return void
+     */
+    public function processAssert(CustomerAccountIndex $customerAccountIndex)
+    {
+        $successMessage = $customerAccountIndex->getMessages()->getSuccessMessages();
+        \PHPUnit_Framework_Assert::assertEquals(
+            self::SUCCESS_MESSAGE,
+            $successMessage,
+            'Wrong success message is displayed.'
+            . "\nExpected: " . self::SUCCESS_MESSAGE
+            . "\nActual: " . $successMessage
+        );
+    }
+
+    /**
+     * Returns success message if equals to expected message
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Success customer info save message on customer account index page is correct.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Address.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Address.php
index ee399ef8aaa7efca33d6911841669839c3a3010e..740aba7e777d73a1e1e3660ac64f299c551827d8 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Address.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/Address.php
@@ -53,7 +53,7 @@ class Address extends DataFixture
             . (isset($data['fields']['middlename']['value']) ? $data['fields']['middlename']['value'] . ' ' : '')
             . $data['fields']['lastname']['value'] . ', '
             . (isset($data['fields']['suffix']['value']) ? $data['fields']['suffix']['value'] . ' ' : '')
-            . $data['fields']['street_1']['value'] . ', '
+            . $data['fields']['street']['value'] . ', '
             . $data['fields']['city']['value'] . ', '
             . $data['fields']['region_id']['value'] . ' '
             . $data['fields']['postcode']['value'] . ', '
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/AddressBook.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/AddressBook.php
index 58edc8d459c0e0a6efcbb53e2ef963cd91193281..d9e08439f22bd1048da826431d914984e34cb9cf 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/AddressBook.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/AddressBook.php
@@ -67,7 +67,7 @@ class AddressBook extends \Mtf\Fixture\DataFixture
         $this->_data = array('fields' => array('address_id' => array(
             'value' => $data['fields']['firstname']['value'] . ' '
                 . $data['fields']['lastname']['value'] . ', '
-                . $data['fields']['street_1']['value'] . ', '
+                . $data['fields']['street']['value'] . ', '
                 . $data['fields']['city']['value'] . ', '
                 . $data['fields']['region_id']['value'] . ' '
                 . $data['fields']['postcode']['value'] . ', '
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerInjectable.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerInjectable.php
index e493d886dd1e48fab0b4138bb87591839a4a6141..910c8760105de9b140cd46c560e98c94a772e40b 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerInjectable.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerInjectable.php
@@ -60,6 +60,12 @@ class CustomerInjectable extends InjectableFixture
         'input' => 'text',
     ];
 
+    protected $id = [
+        'attribute_code' => 'id',
+        'backend_type' => 'virtual',
+        'group' => null,
+    ];
+
     protected $created_at = [
         'attribute_code' => 'created_at',
         'backend_type' => 'static',
@@ -234,6 +240,15 @@ class CustomerInjectable extends InjectableFixture
         'group' => 'account_information',
     ];
 
+    protected $amount_delta = [
+        'attribute_code' => 'amount_delta',
+        'backend_type' => 'static',
+        'is_required' => '1',
+        'default_value' => '',
+        'input' => 'text',
+        'group' => 'store_credit',
+    ];
+
     protected $is_subscribed = [
         'attribute_code' => 'is_subscribed',
         'backend_type' => 'virtual',
@@ -242,11 +257,13 @@ class CustomerInjectable extends InjectableFixture
     protected $password = [
         'attribute_code' => 'password',
         'backend_type' => 'virtual',
+        'group' => null,
     ];
 
     protected $password_confirmation = [
         'attribute_code' => 'password_confirmation',
         'backend_type' => 'virtual',
+        'group' => null,
     ];
 
     public function getConfirmation()
@@ -319,6 +336,11 @@ class CustomerInjectable extends InjectableFixture
         return $this->getData('password_hash');
     }
 
+    public function getAmountDelta()
+    {
+        return $this->getData('amount_delta');
+    }
+
     public function getPrefix()
     {
         return $this->getData('prefix');
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerInjectable.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerInjectable.xml
index 439a6cb0d5d27662a3af8c24ebc08e5312eea0d3..5953126c4a8ca0e01b6180a17e4fdbd23df11135 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerInjectable.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerInjectable.xml
@@ -44,6 +44,11 @@
             <default_value></default_value>
             <input>date</input>
         </created_at>
+        <id>
+            <attribute_code>id</attribute_code>
+            <backend_type>virtual</backend_type>
+            <group>null</group>
+        </id>
         <created_in>
             <attribute_code>created_in</attribute_code>
             <backend_type>varchar</backend_type>
@@ -183,6 +188,14 @@
             <input>text</input>
             <group>account_information</group>
         </taxvat>
+        <amount_delta>
+            <attribute_code>amount_delta</attribute_code>
+            <backend_type>varchar</backend_type>
+            <is_required>0</is_required>
+            <default_value></default_value>
+            <input>text</input>
+            <group>store_credit</group>
+        </amount_delta>
         <website_id>
             <attribute_code>website_id</attribute_code>
             <backend_type>static</backend_type>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountEdit.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountEdit.php
new file mode 100644
index 0000000000000000000000000000000000000000..98dca9d9a249928771c5e042dd007a1d3630d129
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountEdit.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Customer\Test\Page;
+
+use Mtf\Page\FrontendPage;
+
+/**
+ * Class CustomerAccountEdit
+ * Customer account info edit page
+ */
+class CustomerAccountEdit extends FrontendPage
+{
+    const MCA = 'customer/account/edit';
+
+    protected $_blocks = [
+        'accountInfoForm' => [
+            'name' => 'accountInfoForm',
+            'class' => 'Magento\Customer\Test\Block\Form\CustomerForm',
+            'locator' => '#form-validate',
+            'strategy' => 'css selector',
+        ],
+    ];
+
+    /**
+     * @return \Magento\Customer\Test\Block\Form\CustomerForm
+     */
+    public function getAccountInfoForm()
+    {
+        return $this->getBlockInstance('accountInfoForm');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountEdit.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountEdit.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4309564d602be74dced7d1b6f5f4b2e15857984b
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountEdit.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<page mca="customer/account/edit" >
+    <block>
+        <name>accountInfoForm</name>
+        <class>Magento\Customer\Test\Block\Form\CustomerForm</class>
+        <locator>#form-validate</locator>
+        <strategy>css selector</strategy>
+    </block>
+</page>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountIndex.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountIndex.php
index ab1e5b4281214a8cea16fc8d0637cc7381d01778..f1001498cf7b64231182e9b3e0ee98b77f498415 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountIndex.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountIndex.php
@@ -45,7 +45,7 @@ class CustomerAccountIndex extends FrontendPage
         'dashboardAddress' => [
             'name' => 'dashboardAddress',
             'class' => 'Magento\Customer\Test\Block\Account\Dashboard\Address',
-            'locator' => '.block.dashboard.addresses',
+            'locator' => '.block-dashboard-addresses',
             'strategy' => 'css selector',
         ],
         'titleBlock' => [
@@ -60,6 +60,18 @@ class CustomerAccountIndex extends FrontendPage
             'locator' => '.nav.items',
             'strategy' => 'css selector',
         ],
+        'infoBlock' => [
+            'name' => 'infoBlock',
+            'class' => 'Magento\Customer\Test\Block\Account\Dashboard\Info',
+            'locator' => '.column.main',
+            'strategy' => 'css selector',
+        ],
+        'compareProductsBlock' => [
+            'name' => 'compareProductsBlock',
+            'class' => 'Magento\Catalog\Test\Block\Product\Compare\Sidebar',
+            'locator' => '.block.compare',
+            'strategy' => 'css selector',
+        ],
     ];
 
     /**
@@ -95,4 +107,24 @@ class CustomerAccountIndex extends FrontendPage
     {
         return $this->getBlockInstance('accountMenuBlock');
     }
+
+    /**
+     * Get Account Info Block
+     *
+     * @return \Magento\Customer\Test\Block\Account\Dashboard\Info
+     */
+    public function getInfoBlock()
+    {
+        return $this->getBlockInstance('infoBlock');
+    }
+
+    /**
+     * Get compare products block
+     *
+     * @return \Magento\Catalog\Test\Block\Product\Compare\Sidebar
+     */
+    public function getCompareProductsBlock()
+    {
+        return $this->getBlockInstance('compareProductsBlock');
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountIndex.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountIndex.xml
index a550144c4b2731013344f1b420de5d29afa84ca5..26fe9095fdad2670b178d23abbcd1282e27d654b 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountIndex.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAccountIndex.xml
@@ -33,7 +33,7 @@
     <block>
         <name>dashboardAddress</name>
         <class>Magento\Customer\Test\Block\Account\Dashboard\Address</class>
-        <locator>.block.dashboard.addresses</locator>
+        <locator>.block-dashboard-addresses</locator>
         <strategy>css selector</strategy>
     </block>
     <block>
@@ -48,4 +48,16 @@
         <locator>.nav.items</locator>
         <strategy>css selector</strategy>
     </block>
+    <block>
+        <name>infoBlock</name>
+        <class>Magento\Customer\Test\Block\Account\Dashboard\Info</class>
+        <locator>.column.main</locator>
+        <strategy>css selector</strategy>
+    </block>
+    <block>
+        <name>compareProductsBlock</name>
+        <class>Magento\Catalog\Test\Block\Product\Compare\Sidebar</class>
+        <locator>.block.compare</locator>
+        <strategy>css selector</strategy>
+    </block>
 </page>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.php
index 29fa24e366e176067d0b9da8011124423e1d013a..be9ded8b623f15666fe0ff580a7fc8b0ad2bd4ac 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.php
@@ -69,7 +69,7 @@ class Address extends AbstractRepository
                     'company' => array(
                         'value' => 'Magento %isolation%'
                     ),
-                    'street_1' => array(
+                    'street' => array(
                         'value' => '6161 West Centinela Avenue'
                     ),
                     'city' => array(
@@ -125,7 +125,7 @@ class Address extends AbstractRepository
                     'company' => array(
                         'value' => 'Magento %isolation%'
                     ),
-                    'street_1' => array(
+                    'street' => array(
                         'value' => '727 5th Ave'
                     ),
                     'city' => array(
@@ -164,7 +164,7 @@ class Address extends AbstractRepository
                     'company' => array(
                         'value' => 'Magento %isolation%'
                     ),
-                    'street_1' => array(
+                    'street' => array(
                         'value' => '6161 West Centinela Avenue'
                     ),
                     'country_id' => array(
@@ -255,7 +255,7 @@ class Address extends AbstractRepository
                     'telephone' => array(
                         'value' => '444-44-444-44'
                     ),
-                    'street_1' => array(
+                    'street' => array(
                         'value' => '42 King Street West'
                     ),
                     'country_id' => array(
@@ -323,7 +323,7 @@ class Address extends AbstractRepository
                         'value' => 'Germany',
                         'input' => 'select'
                     ),
-                    'street_1' => array(
+                    'street' => array(
                         'value' => 'Augsburger Strabe 41'
                     ),
                     'city' => array(
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/CustomerInjectable.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/CustomerInjectable.php
index 9c271b32400431e7d6b8d64a2262aba34c35834a..85e4d3cf880f2437935b41709d10408416e9e746 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/CustomerInjectable.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/CustomerInjectable.php
@@ -28,8 +28,7 @@ use Mtf\Repository\AbstractRepository;
 
 /**
  * Class CustomerInjectable
- *
- * @package Magento\Customer\Test\Repository
+ * Customer repository
  */
 class CustomerInjectable extends AbstractRepository
 {
@@ -49,6 +48,38 @@ class CustomerInjectable extends AbstractRepository
             'password_confirmation' => '123123q',
         ];
 
+        $this->_data['johndoe'] = [
+            'firstname' => 'John',
+            'lastname' => 'Doe',
+            'email' => 'JohnDoe_%isolation%@example.com',
+            'password' => '123123q',
+            'password_confirmation' => '123123q',
+            'dob' => '01/01/1990',
+            'gender' => 'Male',
+        ];
+
+        $this->_data['johndoe_retailer'] = [
+            'firstname' => 'John',
+            'lastname' => 'Doe',
+            'group_id' => 'Retailer',
+            'email' => 'JohnDoe_%isolation%@example.com',
+            'password' => '123123q',
+            'password_confirmation' => '123123q',
+            'dob' => '01/01/1990',
+            'gender' => 'Male',
+        ];
+
+        $this->_data['johndoe_with_balance'] = [
+            'firstname' => 'John',
+            'lastname' => 'Doe',
+            'email' => 'JohnDoe_%isolation%@example.com',
+            'password' => '123123q',
+            'password_confirmation' => '123123q',
+            'dob' => '01/01/1990',
+            'gender' => 'Male',
+            'amount_delta' => 501
+        ];
+
         $this->_data['defaultBackend'] = [
             'firstname' => 'John',
             'lastname' => 'Doe',
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerFrontendEntity.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerFrontendEntity.php
new file mode 100644
index 0000000000000000000000000000000000000000..da3a56dd0a0c7640894999cbf3ba8e2480b50b8d
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerFrontendEntity.php
@@ -0,0 +1,174 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Customer\Test\TestCase;
+
+use Magento\Customer\Test\Constraint\AssertCustomerInfoSuccessSavedMessage;
+use Magento\Customer\Test\Fixture\AddressInjectable;
+use Magento\Customer\Test\Fixture\CustomerInjectable;
+use Magento\Customer\Test\Page\CustomerAccountEdit;
+use Magento\Customer\Test\Page\CustomerAccountIndex;
+use Magento\Customer\Test\Page\CustomerAddressEdit;
+use Mtf\TestCase\Injectable;
+use Mtf\Fixture\FixtureFactory;
+use Magento\Cms\Test\Page\CmsIndex;
+use Magento\Customer\Test\Page\CustomerAccountLogin;
+
+/**
+ * Test Creation for UpdateCustomerFrontendEntity
+ *
+ * Test Flow:
+ * Preconditions:
+ * 1. Default test customer is created
+ *
+ * Steps:
+ * 1. Login to fronted as test customer from preconditions
+ * 2. Navigate to Account Dashboard page:
+ * 3. Click "Edit" link near "Contact Information"
+ * 4. Fill fields with test data and save
+ * 5. Click "Edit Address" link near "Default Billing Address", save and return to Account Dashboard page
+ * 6. Fill fields with test data and save
+ * 7. Perform all assertions
+ *
+ * @group Customer_Account_(CS)
+ * @ZephyrId MAGETWO-25925
+ */
+class UpdateCustomerFrontendEntity extends Injectable
+{
+    /**
+     * Factory for Fixtures
+     *
+     * @var FixtureFactory
+     */
+    protected $fixtureFactory;
+
+    /**
+     * CmsIndex page
+     *
+     * @var CmsIndex
+     */
+    protected $cmsIndex;
+
+    /**
+     * CustomerAccountLogin page
+     *
+     * @var CustomerAccountLogin
+     */
+    protected $customerAccountLogin;
+
+    /**
+     * CustomerAccountIndex page
+     *
+     * @var CustomerAccountIndex
+     */
+    protected $customerAccountIndex;
+
+    /**
+     * CustomerAccountEdit page
+     *
+     * @var CustomerAccountEdit
+     */
+    protected $customerAccountEdit;
+
+    /**
+     * CustomerAddressEdit page
+     *
+     * @var CustomerAddressEdit
+     */
+    protected $customerAddressEdit;
+
+    /**
+     * Preparing data for test
+     *
+     * @param CmsIndex $cmsIndex
+     * @param FixtureFactory $fixtureFactory
+     * @param CustomerAccountLogin $customerAccountLogin
+     * @param CustomerAccountIndex $customerAccountIndex
+     * @param CustomerAccountEdit $customerAccountEdit
+     * @param CustomerAddressEdit $customerAddressEdit
+     * @return void
+     */
+    public function __inject(
+        CmsIndex $cmsIndex,
+        FixtureFactory $fixtureFactory,
+        CustomerAccountLogin $customerAccountLogin,
+        CustomerAccountIndex $customerAccountIndex,
+        CustomerAccountEdit $customerAccountEdit,
+        CustomerAddressEdit $customerAddressEdit
+    ) {
+        $this->cmsIndex = $cmsIndex;
+        $this->fixtureFactory = $fixtureFactory;
+        $this->customerAccountLogin = $customerAccountLogin;
+        $this->customerAccountIndex = $customerAccountIndex;
+        $this->customerAccountEdit = $customerAccountEdit;
+        $this->customerAddressEdit = $customerAddressEdit;
+    }
+
+    /**
+     * Run Update Customer Entity test
+     *
+     * @param CustomerInjectable $initialCustomer
+     * @param CustomerInjectable $customer
+     * @param AddressInjectable $address
+     * @param AssertCustomerInfoSuccessSavedMessage $assertCustomerInfoSuccessSavedMessage
+     * @return void
+     */
+    public function test(
+        CustomerInjectable $initialCustomer,
+        CustomerInjectable $customer,
+        AddressInjectable $address,
+        AssertCustomerInfoSuccessSavedMessage $assertCustomerInfoSuccessSavedMessage
+    ) {
+        // Preconditions
+        $initialCustomer->persist();
+
+        // Steps
+        $this->cmsIndex->open();
+        $this->cmsIndex->getLinksBlock()->openLink('Log In');
+        $this->customerAccountLogin->getLoginBlock()->fill($initialCustomer);
+        $this->customerAccountLogin->getLoginBlock()->submit();
+
+        $this->customerAccountIndex->getInfoBlock()->openEditContactInfo();
+        $this->customerAccountEdit->getAccountInfoForm()->fill($customer);
+        $this->customerAccountEdit->getAccountInfoForm()->submit();
+
+        \PHPUnit_Framework_Assert::assertThat($this->getName(), $assertCustomerInfoSuccessSavedMessage);
+
+        $this->customerAccountIndex->getDashboardAddress()->editBillingAddress();
+        $this->customerAddressEdit->getEditForm()->fill($address);
+        $this->customerAddressEdit->getEditForm()->saveAddress();
+    }
+
+    /**
+     * Customer logout from account
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        if ($this->cmsIndex->getLinksBlock()->isVisible()) {
+            $this->cmsIndex->getLinksBlock()->openLink('Log Out');
+        }
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerFrontendEntity/test.csv b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerFrontendEntity/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..739a564e68628dcdbfc136e38b3f4c9c89335c20
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerFrontendEntity/test.csv
@@ -0,0 +1,3 @@
+"customer/data/firstname";"customer/data/lastname";"customer/data/email";"address/data/firstname";"address/data/lastname";"address/data/company";"address/data/street";"address/data/city";"address/data/country_id";"address/data/region_id";"address/data/region";"address/data/telephone";"address/data/fax";"address/data/postcode";"constraint"
+"Jany %isolation%";"Doe %isolation%";"janydoe%isolation%@example.com";"Jany %isolation%";"Doe %isolation%";"Company %isolation%";"Some street %isolation%";"City %isolation%";"United States";"Colorado";"-";"555-888-111-999";"161-999-8888";"12345";"assertCustomerAddressSuccessSaveMessage, assertCustomerDefaultAddresses"
+"Jonny %isolation%";"Doe %isolation%";"jonny%isolation%@example.com";"John %isolation%";"Doe %isolation%";"Company %isolation%";"Some street %isolation%";"City %isolation%";"United Kingdom";"-";"Region %isolation%";"0123456789-02134567";"5555-874-99634";"12345";"assertCustomerAddressSuccessSaveMessage, assertCustomerDefaultAddresses"
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/etc/global/constraint.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/etc/global/constraint.xml
index 87100e00439d0fdd00d444a86aa46bdcaa3129b7..a235bf6c8a7a2a22061b407ddb4393c5c1e4f66e 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/etc/global/constraint.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/etc/global/constraint.xml
@@ -102,4 +102,23 @@
     <assertCustomerGroupForm module="Magento_Customer">
         <severeness>low</severeness>
     </assertCustomerGroupForm>
+    <assertCustomerInfoSuccessSavedMessage module="Magento_Customer">
+        <severeness>low</severeness>
+        <require>
+            <customerAccountIndex class="Magento\Customer\Test\Page\CustomerAccountIndex" />
+        </require>
+    </assertCustomerInfoSuccessSavedMessage>
+    <assertCustomerAddressSuccessSaveMessage module="Magento_Customer">
+        <severeness>low</severeness>
+        <require>
+            <customerAccountIndex class="Magento\Customer\Test\Page\CustomerAccountIndex" />
+        </require>
+    </assertCustomerAddressSuccessSaveMessage>
+    <assertCustomerDefaultAddresses module="Magento_Customer">
+        <severeness>low</severeness>
+        <require>
+            <customerAccountIndex class="Magento\Customer\Test\Page\CustomerAccountIndex" />
+            <address class="Magento\Customer\Test\Fixture\AddressInjectable" />
+        </require>
+    </assertCustomerDefaultAddresses>
 </constraint>
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/etc/global/page.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/etc/global/page.xml
index 968424e9029fb5f5757530d32ad8fd2b19dd9c17..c1ef19574065900460016eb4698ecbc9d82e5a6a 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/etc/global/page.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/etc/global/page.xml
@@ -32,6 +32,10 @@
         <mca>customer/account/index</mca>
         <class>Magento\Customer\Test\Page\CustomerAccountIndex</class>
     </customerAccountIndex>
+    <customerAccountEdit>
+        <mca>customer/account/edit</mca>
+        <class>Magento\Customer\Test\Page\CustomerAccountEdit</class>
+    </customerAccountEdit>
     <customerIndex>
         <mca>customer/index</mca>
         <area>adminhtml</area>
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Constraint/AssertDownloadableDuplicateForm.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Constraint/AssertDownloadableDuplicateForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..b831d11b23e7ad4bc32947a51a9b83869c37d2d6
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Constraint/AssertDownloadableDuplicateForm.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Downloadable\Test\Constraint;
+
+use Mtf\Fixture\FixtureInterface;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Catalog\Test\Constraint\AssertProductDuplicateForm;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+
+/**
+ * Class AssertDownloadableDuplicateForm
+ */
+class AssertDownloadableDuplicateForm extends AssertProductDuplicateForm
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert form data equals duplicate product downloadable data
+     *
+     * @param FixtureInterface $product
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductEdit $productPage
+     * @return void
+     */
+    public function processAssert(
+        FixtureInterface $product,
+        CatalogProductIndex $productGrid,
+        CatalogProductEdit $productPage
+    ) {
+        $filter = ['sku' => $product->getSku() . '-1'];
+        $productGrid->open()->getProductGrid()->searchAndOpen($filter);
+
+        $formData = $productPage->getForm()->getData($product);
+        $fixtureData = $this->convertDownloadableArray($this->prepareFixtureData($product->getData()));
+        $errors = $this->verifyData($fixtureData, $formData);
+
+        \PHPUnit_Framework_Assert::assertEmpty($errors, $errors);
+    }
+
+    /**
+     * Sort downloadable array
+     *
+     * @param array $fields
+     * @return array
+     */
+    protected function sortDownloadableArray(array $fields)
+    {
+        usort(
+            $fields,
+            function ($row1, $row2) {
+                if ($row1['sort_order'] == $row2['sort_order']) {
+                    return 0;
+                }
+
+                return ($row1['sort_order'] < $row2['sort_order']) ? -1 : 1;
+            }
+        );
+
+        return $fields;
+    }
+
+    /**
+     * Convert fixture array
+     *
+     * @param array $fields
+     * @return array
+     */
+    protected function convertDownloadableArray(array $fields)
+    {
+        if (isset($fields['downloadable_links']['downloadable']['link'])) {
+            $fields['downloadable_links']['downloadable']['link'] = $this->sortDownloadableArray(
+                $fields['downloadable_links']['downloadable']['link']
+            );
+        }
+        if (isset($fields['downloadable_sample']['downloadable']['sample'])) {
+            $fields['downloadable_sample']['downloadable']['sample'] = $this->sortDownloadableArray(
+                $fields['downloadable_sample']['downloadable']['sample']
+            );
+        }
+
+        return $fields;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Constraint/AssertDownloadableProductForm.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Constraint/AssertDownloadableProductForm.php
old mode 100644
new mode 100755
index f66ca5e12877e1ca3bb3c45bf2290f9937de5627..c52f86168016c2e3e3c7ce92ad9dab9f38722659
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Constraint/AssertDownloadableProductForm.php
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Constraint/AssertDownloadableProductForm.php
@@ -24,10 +24,10 @@
 
 namespace Magento\Downloadable\Test\Constraint;
 
-use Magento\Catalog\Test\Constraint\AssertProductForm;
 use Mtf\Fixture\FixtureInterface;
-use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Catalog\Test\Constraint\AssertProductForm;
 use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
 
 /**
  * Class AssertDownloadableProductForm
@@ -35,6 +35,13 @@ use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
  */
 class AssertDownloadableProductForm extends AssertProductForm
 {
+    /**
+     * Sort fields for fixture and form data
+     *
+     * @var array
+     */
+    protected $sortFields = ['downloadable_links/downloadable/link::sort_order'];
+
     /**
      * Constraint severeness
      *
@@ -58,51 +65,10 @@ class AssertDownloadableProductForm extends AssertProductForm
         $filter = ['sku' => $product->getData('sku')];
         $productGrid->open()->getProductGrid()->searchAndOpen($filter);
 
-        $fields = $this->convertDownloadableArray($this->prepareFixtureData($product));
-
-        $fieldsForm = $productPage->getForm()->getData($product);
-        \PHPUnit_Framework_Assert::assertEquals($fields, $fieldsForm, 'Form data not equals fixture data.');
-    }
-
-    /**
-     * Sort downloadable array
-     *
-     * @param array $fields
-     * @return array
-     */
-    protected function sortDownloadableArray(&$fields)
-    {
-        usort(
-            $fields,
-            function ($row1, $row2) {
-                if ($row1['sort_order'] == $row2['sort_order']) {
-                    return 0;
-                }
-                return ($row1['sort_order'] < $row2['sort_order']) ? -1 : 1;
-            }
-        );
-    }
-
-    /**
-     * Convert fixture array
-     *
-     * @param array $fields
-     * @return array
-     */
-    protected function convertDownloadableArray(array $fields)
-    {
-        if (isset($fields['downloadable_links']['downloadable']['link'])) {
-            $this->sortDownloadableArray(
-                $fields['downloadable_links']['downloadable']['link']
-            );
-        }
-        if (isset($fields['downloadable_sample']['downloadable']['sample'])) {
-            $this->sortDownloadableArray(
-                $fields['downloadable_sample']['downloadable']['sample']
-            );
-        }
-
-        return $fields;
+        $fieldsFixture = $this->prepareFixtureData($product->getData(), $this->sortFields);
+        $fieldsForm = $this->prepareFormData($productPage->getForm()->getData($product), $this->sortFields);
+        $error = $this->verifyData($fieldsFixture, $fieldsForm);
+        \PHPUnit_Framework_Assert::assertEmpty($error, $error);
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable.php
index 8194ce7e3e85aaa74be140c1c1bb1866db1bab72..cee9b2e3e56186ae0a9ea354731905d1812a72b0 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable.php
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable.php
@@ -381,13 +381,8 @@ class CatalogProductDownloadable extends InjectableFixture
         'is_required' => '1',
         'default_value' => '',
         'input' => 'price',
-        'group' => 'product-details'
-    ];
-
-    protected $inventory_manage_stock = [
-        'attribute_code' => 'inventory_manage_stock',
-        'input' => 'select',
-        'group' => 'advanced-inventory',
+        'group' => 'product-details',
+        'source' => 'Magento\Catalog\Test\Fixture\CatalogProductSimple\Price',
     ];
 
     protected $stock_data = [
@@ -396,24 +391,6 @@ class CatalogProductDownloadable extends InjectableFixture
         'group' => 'advanced-inventory',
     ];
 
-    protected $stock_data_min_qty = [
-        'attribute_code' => 'stock_data',
-        'input' => 'text',
-        'group' => 'advanced-inventory',
-    ];
-
-    protected $stock_data_use_config_min_qty = [
-        'attribute_code' => 'stock_data_use_config_min_qty',
-        'input' => 'checkbox',
-        'group' => 'advanced-inventory'
-    ];
-
-    protected $inventory_qty = [
-        'attribute_code' => 'inventory_qty',
-        'input' => 'text',
-        'group' => 'advanced-inventory',
-    ];
-
     protected $quantity_and_stock_status = [
         'attribute_code' => 'quantity_and_stock_status',
         'backend_type' => 'int',
@@ -666,7 +643,9 @@ class CatalogProductDownloadable extends InjectableFixture
 
     protected $website_ids = [
         'attribute_code' => 'website_ids',
-        'backend_type' => 'virtual'
+        'backend_type' => 'virtual',
+        'default_value' => ['Main Website'],
+        'group' => 'websites',
     ];
 
     public function getCategoryIds()
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable.xml b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable.xml
old mode 100644
new mode 100755
index 34b7746109a689b15c2c8c87b8d062ee4669f6aa..e83b7dea98518d8a973b6e8a2ca688d787f4d6ab
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable.xml
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable.xml
@@ -86,6 +86,7 @@
             <is_required>0</is_required>
             <default_value></default_value>
             <input>textarea</input>
+            <group>product-details</group>
         </description>
         <gallery>
             <attribute_code>gallery</attribute_code>
@@ -261,6 +262,7 @@
             <is_required>1</is_required>
             <default_value></default_value>
             <input>price</input>
+            <source>Magento\Catalog\Test\Fixture\CatalogProductSimple\Price</source>
         </price>
         <related_tgtr_position_behavior>
             <attribute_code>related_tgtr_position_behavior</attribute_code>
@@ -296,6 +298,7 @@
             <is_required>0</is_required>
             <default_value></default_value>
             <input>textarea</input>
+            <group>autosetting</group>
         </short_description>
         <sku>
             <attribute_code>sku</attribute_code>
@@ -448,6 +451,12 @@
             <attribute_code>stock_data_min_qty</attribute_code>
             <input>text</input>
         </stock_data_min_qty>
+        <website_ids>
+            <attribute_code>website_ids</attribute_code>
+            <backend_type>virtual</backend_type>
+            <default_value>Main Website</default_value>
+            <group>websites</group>
+        </website_ids>
     </fields>
     <data_set>
         <sku></sku>
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/DownloadableProduct.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/DownloadableProduct.php
index 2cf30517f9034c5632773127c6470e14d125294b..29d7bc57ff924bc300a0755ed02df7918575502f 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/DownloadableProduct.php
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/DownloadableProduct.php
@@ -59,7 +59,26 @@ class DownloadableProduct extends Product
             'price' => [
                 'value' => '1',
                 'group' => static::GROUP_PRODUCT_DETAILS
-            ]
+            ],
+            'qty' => array(
+                'value' => 1000,
+                'group' => static::GROUP_PRODUCT_DETAILS,
+                'input_name' => 'product[quantity_and_stock_status][qty]'
+            ),
+            'quantity_and_stock_status' => array(
+                'value' => 'In Stock',
+                'input_value' => 1,
+                'group' => static::GROUP_PRODUCT_DETAILS,
+                'input_name' => 'product[quantity_and_stock_status][is_in_stock]'
+            ),
+            'product_website_1' => array(
+                'value' => 'Yes',
+                'input_value' => 1,
+                'group' => static::GROUP_PRODUCT_WEBSITE,
+                'input' => 'checkbox',
+                'input_name' => 'product[website_ids][]'
+            ),
+
         );
 
         $this->_data['fields'] = $data + $this->_data['fields'];
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Handler/CatalogProductDownloadable/Curl.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Handler/CatalogProductDownloadable/Curl.php
index ca5aead81bec4fcdbd4acdd85037a61be6cdcaa7..917ec398302d271c917bc19767f7252a637c98e9 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Handler/CatalogProductDownloadable/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Handler/CatalogProductDownloadable/Curl.php
@@ -66,10 +66,40 @@ class Curl extends ProductCurl implements CatalogProductDownloadableInterface
     protected function prepareData(FixtureInterface $fixture, $prefix = null)
     {
         $data = parent::prepareData($fixture, null);
-        $downloadable = $data['downloadable'];
-        unset($data['downloadable']);
+
+        $downloadableData = [];
+        if (!empty($data['downloadable_links'])) {
+            $data['links_title'] = $data['downloadable_links']['title'];
+            foreach ($data['downloadable_links']['downloadable']['link'] as $key => $link) {
+                $downloadableData['downloadable']['link'][$key]['title'] = $link['title'];
+                // only url type
+                $downloadableData['downloadable']['link'][$key]['type'] = 'url';
+                $downloadableData['downloadable']['link'][$key]['link_url'] = $link['file_link_url'];
+                $downloadableData['downloadable']['link'][$key]['price'] = $link['price'];
+                $downloadableData['downloadable']['link'][$key]['number_of_downloads'] = $link['number_of_downloads'];
+                $downloadableData['downloadable']['link'][$key]['is_shareable'] = $link['is_shareable'];
+                $downloadableData['downloadable']['link'][$key]['sort_order'] = $link['sort_order'];
+                // only url type
+                $downloadableData['downloadable']['link'][$key]['sample']['type'] = 'url';
+                $downloadableData['downloadable']['link'][$key]['sample']['url'] = $link['sample']['sample_url'];
+            }
+            unset($data['downloadable_links']);
+        }
+
+        if (!empty($data['downloadable_sample'])) {
+            $data['samples_title'] = $data['downloadable_sample']['title'];
+            foreach ($data['downloadable_sample']['downloadable']['sample'] as $key => $sample) {
+                $downloadableData['downloadable']['sample'][$key]['title'] = $sample['title'];
+                // only url type
+                $downloadableData['downloadable']['sample'][$key]['type'] = 'url';
+                $downloadableData['downloadable']['sample'][$key]['sample_url'] = $sample['sample_url'];
+                $downloadableData['downloadable']['sample'][$key]['sort_order'] = $sample['sort_order'];
+            }
+            unset($data['downloadable_sample']);
+        }
+
         $data = $prefix ? [$prefix => $data] : $data;
-        $data['downloadable'] = $downloadable;
+        $data = array_merge($data, $downloadableData);
 
         return $this->replaceMappingData($data);
     }
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Handler/Curl/CreateDownloadable.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Handler/Curl/CreateDownloadable.php
index b7c2d936812dbaed31dc3d0d196be6218efc3d43..7c5ddb2eb8838516ef08a4ddf1e91d28664580ba 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Handler/Curl/CreateDownloadable.php
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Handler/Curl/CreateDownloadable.php
@@ -52,9 +52,8 @@ class CreateDownloadable extends Curl
                     continue;
                 }
                 if (isset($values['input_name'])) {
-                    $key = $values['input_name'];
-                }
-                if ($prefix) {
+                    $data[$values['input_name']] = $value;
+                } elseif ($prefix) {
                     $data[$prefix][$key] = $value;
                 } else {
                     $data[$key] = $value;
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Repository/CatalogProductDownloadable.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Repository/CatalogProductDownloadable.php
index e13fb5242c35889f0964e68c861cd71404677e75..69f62020455072ab10d9b9579fde9367acb144d5 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Repository/CatalogProductDownloadable.php
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Repository/CatalogProductDownloadable.php
@@ -45,7 +45,7 @@ class CatalogProductDownloadable extends AbstractRepository
         $this->_data['default'] = [
             'name' => 'Test downloadable product %isolation%',
             'sku' => 'sku_test_downloadable_product_%isolation%',
-            'price' => 280.00,
+            'price' => ['value' => 280.00, 'preset' => '-'],
             'type_id' => 'downloadable',
             'tax_class_id' => ['dataSet' => 'Taxable Goods'],
             'quantity_and_stock_status' => [
@@ -55,30 +55,8 @@ class CatalogProductDownloadable extends AbstractRepository
             'status' => 'Product online',
             'visibility' => 'Catalog, Search',
             'url_key' => 'test-downloadable-product-%isolation%',
-            'stock_data' => [
-                'manage_stock' => 'Yes',
-                'qty' => 90.0000,
-                'is_in_stock' => 'Yes'
-            ],
             'is_virtual' => 'Yes',
-            'links_title' => 'Links',
-            'links_purchased_separately' => 'Yes',
-            'downloadable' => [
-                'link' => [
-                    [
-                        'title' => 'Link title',
-                        'price' => '1',
-                        'number_of_downloads' => 1,
-                        'is_shareable' => 'Use config',
-                        'sample' => [
-                            'type' => 'url',
-                            'url' => 'http://example.com/',
-                        ],
-                        'type' => 'url',
-                        'link_url' => 'http://example.com/',
-                    ]
-                ]
-            ],
+            'downloadable_links' => ['preset' => 'default'],
             'website_ids' => ['Main Website'],
         ];
     }
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/Create/LinksPurchasedSeparatelyTest.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/Create/LinksPurchasedSeparatelyTest.php
old mode 100644
new mode 100755
index b05377f2d3e87ed87923e83741d37029a202015d..b45347461cb8a21176f9014f9e10b0f7eb28a522
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/Create/LinksPurchasedSeparatelyTest.php
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/Create/LinksPurchasedSeparatelyTest.php
@@ -58,12 +58,13 @@ class LinksPurchasedSeparatelyTest extends Functional
     {
         $createProductPage = Factory::getPageFactory()->getCatalogProductIndex();
         $createProductPage->open();
-        $createProductPage->getProductBlock()->addProduct('downloadable');
+        $createProductPage->getGridPageActionBlock()->addProduct('downloadable');
 
         $createProductPageNew = Factory::getPageFactory()->getCatalogProductNew();
         $productBlockForm = $createProductPageNew->getForm();
 
-        $productBlockForm->fillProduct($this->product);
+        $category = $this->product->getCategories()['category'];
+        $productBlockForm->fill($this->product, null, $category);
         $createProductPageNew->getFormAction()->save();
 
         $createProductPageNew->getMessagesBlock()->assertSuccessMessage();
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/CreateDownloadableProductEntityTest.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/CreateDownloadableProductEntityTest.php
index 12b34392d648e56e00a6cd7c0b13af05236b0577..7c7f564bc8f604fcf7806eeff524c7133086410b 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/CreateDownloadableProductEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/CreateDownloadableProductEntityTest.php
@@ -88,6 +88,7 @@ class CreateDownloadableProductEntityTest extends Injectable
      * @param CatalogCategory $category
      * @param CatalogProductIndex $catalogProductIndexNewPage
      * @param CatalogProductNew $catalogProductNewPage
+     * @return void
      */
     public function __inject(
         CatalogCategory $category,
@@ -104,13 +105,14 @@ class CreateDownloadableProductEntityTest extends Injectable
      *
      * @param CatalogProductDownloadable $product
      * @param CatalogCategory $category
+     * @return void
      */
     public function testCreateDownloadableProduct(CatalogProductDownloadable $product, CatalogCategory $category)
     {
         $this->catalogProductIndex->open();
-        $this->catalogProductIndex->getProductBlock()->addProduct('downloadable');
+        $this->catalogProductIndex->getGridPageActionBlock()->addProduct('downloadable');
         $productBlockForm = $this->catalogProductNew->getForm();
-        $productBlockForm->fillProduct($product, $category);
+        $productBlockForm->fill($product, null, $category);
         $this->catalogProductNew->getFormAction()->save();
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/CreateDownloadableProductEntityTest/testCreateDownloadableProduct.csv b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/CreateDownloadableProductEntityTest/testCreateDownloadableProduct.csv
old mode 100644
new mode 100755
index 19443badf94798f2c292c5fd8ea942adcbd1dcd6..5e5d12355e27b1b620d4359a09964901576a8d1f
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/CreateDownloadableProductEntityTest/testCreateDownloadableProduct.csv
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/CreateDownloadableProductEntityTest/testCreateDownloadableProduct.csv
@@ -1,15 +1,15 @@
 product/data/name;product/data/sku;product/data/price;product/data/tax_class_id/dataSet;product/data/quantity_and_stock_status/qty;product/data/quantity_and_stock_status/is_in_stock;product/data/is_virtual;product/data/category;product/data/description;product/data/short_description;product/data/inventory_manage_stock;product/data/inventory_qty;product/data/stock_data_use_config_min_qty;product/data/stock_data_min_qty;product/data/downloadable_sample/preset;product/data/downloadable_links/preset;product/data/custom_options/preset;product/data/special_price;product/data/group_price/preset;product/data/tier_price/preset;constraint
 DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;100;Taxable Goods;1;In Stock;Yes;Default Category;-;-;-;-;-;-;-;default;-;-;-;-;assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductVisibleInCategory, assertProductPage, assertProductInStock
 DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;1;Taxable Goods;10;In Stock;Yes;category %isolation%;-;-;-;-;-;-;default;default;-;-;-;-;assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductVisibleInCategory, assertDownloadableSamplesData, assertDownloadableLinksData
-DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;33;Taxable Goods;10;In Stock;Yes;category %isolation%;-;-;-;-;-;-;-;default;default;-;-;-;assertProductSaveMessage, assertDownloadableProductForm, assertCustomOptionsOnProductPage, assertProductVisibleInCategory, assertProductPage, assertDownloadableLinksData
-DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;55;Taxable Goods;10;In Stock;Yes;-;-;-;-;-;-;-;with_three_samples;with_three_links;two_options;-;-;-;assertProductSaveMessage, assertCustomOptionsOnProductPage, assertProductInGrid, assertDownloadableProductForm, assertProductVisibleInCategory, assertProductPage, assertDownloadableLinksData, assertProductInStock, assertProductSearchableBySku
+DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;33;Taxable Goods;10;In Stock;Yes;category %isolation%;-;-;-;-;-;-;-;default;default;-;-;-;assertProductSaveMessage, assertDownloadableProductForm, assertProductCustomOptionsOnProductPage, assertProductVisibleInCategory, assertProductPage, assertDownloadableLinksData
+DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;55;Taxable Goods;10;In Stock;Yes;-;-;-;-;-;-;-;with_three_samples;with_three_links;two_options;-;-;-;assertProductSaveMessage, assertProductCustomOptionsOnProductPage, assertProductInGrid, assertDownloadableProductForm, assertProductVisibleInCategory, assertProductPage, assertDownloadableLinksData, assertProductInStock, assertProductSearchableBySku
 DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;100;Taxable Goods;50;Out of Stock;Yes;Default Category;-;-;-;-;-;-;-;default;-;-;-;-;assertProductSaveMessage, assertProductOutOfStock, assertProductInGrid, assertDownloadableProductForm
 DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;9999;Taxable Goods;-;-;Yes;Default Category;-;-;Yes;123;No;123;-;default;-;-;-;-;assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductOutOfStock
 DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;98;None;5;In Stock;Yes;Default Category;This is description for downloadable product;-;-;-;-;-;-;default;-;-;-;-;assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage
-DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;57;Taxable Goods;10;In Stock;Yes;category %isolation%;-;This is short description for downloadable product;-;-;-;-;default;with_three_links;default;-;-;-;assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage, assertCustomOptionsOnProductPage, assertDownloadableSamplesData, assertDownloadableLinksData
-DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;65;Taxable Goods;11;In Stock;Yes;category %isolation%;This is description for downloadable product;This is short description for downloadable product;-;-;-;-;default;with_three_links;default;-;-;-;assertProductSaveMessage, assertProductPage, assertProductInGrid, assertDownloadableProductForm, assertCustomOptionsOnProductPage, assertDownloadableSamplesData, assertDownloadableLinksData
-DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;65;Taxable Goods;11;In Stock;Yes;category %isolation%;-;-;-;-;-;-;default;with_three_links;default;-;-;-;assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage, assertDownloadableLinksData, assertCustomOptionsOnProductPage
+DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;57;Taxable Goods;10;In Stock;Yes;category %isolation%;-;This is short description for downloadable product;-;-;-;-;default;with_three_links;default;-;-;-;assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage, assertProductCustomOptionsOnProductPage, assertDownloadableSamplesData, assertDownloadableLinksData
+DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;65;Taxable Goods;11;In Stock;Yes;category %isolation%;This is description for downloadable product;This is short description for downloadable product;-;-;-;-;default;with_three_links;default;-;-;-;assertProductSaveMessage, assertProductPage, assertProductInGrid, assertDownloadableProductForm, assertProductCustomOptionsOnProductPage, assertDownloadableSamplesData, assertDownloadableLinksData
+DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;65;Taxable Goods;11;In Stock;Yes;category %isolation%;-;-;-;-;-;-;default;with_three_links;default;-;-;-;assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage, assertDownloadableLinksData, assertProductCustomOptionsOnProductPage
 DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;100;Taxable Goods;-;-;Yes;Default Category;-;-;-;-;-;-;-;default;-;-;-;-;assertProductSaveMessage, assertDownloadableProductForm, assertProductVisibleInCategory, assertProductPage
-DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;10;Taxable Goods;10;In Stock;Yes;category %isolation%;-;-;-;-;-;-;-;-;-;5;-;-;assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage, assertSpecialPriceOnProductPage
-DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;365;Taxable Goods;23;In Stock;Yes;category %isolation%;-;-;-;-;-;-;-;-;-;-;default;-;assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage, assertGroupedPriceOnProductPage
-DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;250;Taxable Goods;65;In Stock;Yes;category %isolation%;-;-;-;-;-;-;-;-;-;-;-;default;assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage, assertTierPriceOnProductPage
\ No newline at end of file
+DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;10;Taxable Goods;10;In Stock;Yes;category %isolation%;-;-;-;-;-;-;-;-;-;5;-;-;assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage, assertProductSpecialPriceOnProductPage
+DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;365;Taxable Goods;23;In Stock;Yes;category %isolation%;-;-;-;-;-;-;-;-;-;-;default;-;assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage, assertProductGroupedPriceOnProductPage
+DownloadableProduct_%isolation%;DownloadableProduct_%isolation%;250;Taxable Goods;65;In Stock;Yes;category %isolation%;-;-;-;-;-;-;-;-;-;-;-;default;assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage, assertProductTierPriceOnProductPage
\ No newline at end of file
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/UpdateDownloadableProductEntityTest.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/UpdateDownloadableProductEntityTest.php
index 3a601fb7e55b5ee914a26e6ef372d470d1efdbfd..0c0de0794e321460be47f6792c72dc235f72f94d 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/UpdateDownloadableProductEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/UpdateDownloadableProductEntityTest.php
@@ -122,7 +122,7 @@ class UpdateDownloadableProductEntityTest extends Injectable
         $filter = ['sku' => $this->product->getSku()];
         $this->catalogProductIndex->open()->getProductGrid()->searchAndOpen($filter);
         $productBlockForm = $this->catalogProductEdit->getForm();
-        $productBlockForm->fillProduct($product, $category);
+        $productBlockForm->fill($product, null, $category);
         $this->catalogProductEdit->getFormAction()->save();
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/UpdateDownloadableProductEntityTest/testUpdateDownloadableProduct.csv b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/UpdateDownloadableProductEntityTest/testUpdateDownloadableProduct.csv
index dad29f9cefecde208aaf75546ec68253d650d9dc..9476d7b7a89d654a4d61bdba664dcaba86223cef 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/UpdateDownloadableProductEntityTest/testUpdateDownloadableProduct.csv
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/UpdateDownloadableProductEntityTest/testUpdateDownloadableProduct.csv
@@ -1,8 +1,8 @@
 "product/data/name";"product/data/sku";"product/data/price";"product/data/tax_class_id/dataSet";"product/data/quantity_and_stock_status/qty";"product/data/quantity_and_stock_status/is_in_stock";"product/data/is_virtual";"product/data/weight";"product/data/category";"product/data/description";"product/data/short_description";"product/data/inventory_manage_stock";"product/data/inventory_qty";"product/data/stock_data_use_config_min_qty";"product/data/stock_data_min_qty";"product/data/downloadable_sample/preset";"product/data/downloadable_links/preset";"product/data/custom_options/preset";"product/data/special_price";"isRequired";"constraint"
-"DownloadableProduct_%isolation%";"DownloadableProduct_%isolation%";"55";"Taxable Goods";"10";"In Stock";"Yes";"-";"-";"-";"-";"-";"-";"-";"-";"with_three_samples";"with_three_links";"two_options";"-";"No";"assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage, assertDownloadableLinksData, assertProductInStock, assertCustomOptionsOnProductPage, assertProductSearchableBySku"
+"DownloadableProduct_%isolation%";"DownloadableProduct_%isolation%";"55";"Taxable Goods";"10";"In Stock";"Yes";"-";"-";"-";"-";"-";"-";"-";"-";"with_three_samples";"with_three_links";"two_options";"-";"No";"assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage, assertDownloadableLinksData, assertProductInStock, assertProductCustomOptionsOnProductPage, assertProductSearchableBySku"
 "DownloadableProduct_%isolation%";"DownloadableProduct_%isolation%";"100";"Taxable Goods";"50";"Out of Stock";"Yes";"-";"Default Category";"-";"-";"-";"-";"-";"-";"-";"default";"-";"-";"No";"assertProductSaveMessage, assertProductOutOfStock, assertProductInGrid, assertDownloadableProductForm"
 "DownloadableProduct_%isolation%";"DownloadableProduct_%isolation%";"9999";"Taxable Goods";"123";"-";"Yes";"-";"Default Category";"-";"-";"Yes";"-";"No";"123";"-";"-";"-";"-";"No";"assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductOutOfStock"
 "DownloadableProduct_%isolation%";"DownloadableProduct_%isolation%";"48";"None";"5";"In Stock";"Yes";"-";"Default Category";"This is description for downloadable product";"-";"-";"-";"-";"-";"-";"default";"-";"-";"No";"assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage"
-"DownloadableProduct_%isolation%";"DownloadableProduct_%isolation%";"54";"Taxable Goods";"10";"In Stock";"Yes";"-";"category %isolation%";"-";"This is short description for downloadable product";"-";"-";"-";"-";"default";"with_three_links";"default";"-";"Yes";"assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage, assertCustomOptionsOnProductPage, assertDownloadableSamplesData, assertDownloadableLinksData, assertProductInCategory"
+"DownloadableProduct_%isolation%";"DownloadableProduct_%isolation%";"54";"Taxable Goods";"10";"In Stock";"Yes";"-";"category %isolation%";"-";"This is short description for downloadable product";"-";"-";"-";"-";"default";"with_three_links";"default";"-";"Yes";"assertProductSaveMessage, assertProductInGrid, assertDownloadableProductForm, assertProductPage, assertProductCustomOptionsOnProductPage, assertDownloadableSamplesData, assertDownloadableLinksData, assertProductInCategory"
 "DownloadableProduct_%isolation%";"DownloadableProduct_%isolation%";"57";"Taxable Goods";"10";"In Stock";"No";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"No";"assertProductSaveMessage, assertProductInGrid"
-"DownloadableProduct_%isolation%";"DownloadableProduct_%isolation%";"43";"Taxable Goods";"10";"In Stock";"No";"10";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"40";"No";"assertProductSaveMessage, assertProductInGrid, assertSpecialPriceOnProductPage, assertProductPage"
+"DownloadableProduct_%isolation%";"DownloadableProduct_%isolation%";"43";"Taxable Goods";"10";"In Stock";"No";"10";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"40";"No";"assertProductSaveMessage, assertProductInGrid, assertProductSpecialPriceOnProductPage, assertProductPage"
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/etc/global/constraint.xml b/dev/tests/functional/tests/app/Magento/Downloadable/Test/etc/global/constraint.xml
index e2332785b79ea18770f035f1adf43b6e0dfc19ab..2e24ac40083a775527f6c575c7a7b3a7ae0812ff 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/etc/global/constraint.xml
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/etc/global/constraint.xml
@@ -33,4 +33,12 @@
     <assertDownloadableProductForm module="Magento_Downloadable">
         <severeness>low</severeness>
     </assertDownloadableProductForm>
+    <assertDownloadableDuplicateForm module="Magento_Downloadable">
+        <severeness>high</severeness>
+        <require>
+            <productGrid class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex" />
+            <productPage class="Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit" />
+            <product class="Mtf\Fixture\FixtureInterface" />
+        </require>
+    </assertDownloadableDuplicateForm>
 </constraint>
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Block/Adminhtml/Types/Edit/GoogleShoppingForm.php b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Block/Adminhtml/Types/Edit/GoogleShoppingForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..aec5eca6ab58d73cb9aa45e13ff91bcf313946bf
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Block/Adminhtml/Types/Edit/GoogleShoppingForm.php
@@ -0,0 +1,114 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GoogleShopping\Test\Block\Adminhtml\Types\Edit;
+
+use Mtf\Block\Form;
+use Mtf\Client\Element;
+use Mtf\Client\Element\Locator;
+
+/**
+ * Class GoogleShoppingForm
+ * Google Shopping form
+ */
+class GoogleShoppingForm extends Form
+{
+    /**
+     * Attribute options locator
+     *
+     * @var string
+     */
+    protected $attributeOptions = '//select[@id="gcontent_attribute_0_attribute"]//option';
+
+    /**
+     * Loading Mask locator
+     *
+     * @var string
+     */
+    protected $loadingMask = '//ancestor::body/div[@id="loading-mask"]';
+
+    /**
+     * Fill specified form data
+     *
+     * @param array $fields
+     * @param Element $element
+     * @return void
+     */
+    protected function _fill(array $fields, Element $element = null)
+    {
+        $context = ($element === null) ? $this->_rootElement : $element;
+        foreach ($fields as $field) {
+            $element = $this->getElement($context, $field);
+            if ($this->mappingMode || ($element->isVisible() && !$element->isDisabled())) {
+                $element->setValue($field['value']);
+                $this->waitForElementNotVisible($this->loadingMask, Locator::SELECTOR_XPATH);
+            }
+        }
+    }
+
+    /**
+     * Find Attribute in Attribute set mapping form
+     *
+     * @param string $attributeName
+     * @return bool
+     */
+    public function findAttribute($attributeName)
+    {
+        $attributes = $this->getOptions();
+        foreach ($attributes as $attribute) {
+            if ($attribute == $attributeName) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Click "Add New Attribute" button
+     *
+     * @return void
+     */
+    public function clickAddNewAttribute()
+    {
+        $this->_rootElement->find('#add_new_attribute')->click();
+    }
+
+    /**
+     * Getting all options in select list
+     *
+     * @return array
+     */
+    protected function getOptions()
+    {
+        $elements = $this->_rootElement->find($this->attributeOptions, Locator::SELECTOR_XPATH)->getElements();
+
+        $options = [];
+        foreach ($elements as $key => $element) {
+            $options[$key] = $element->getText();
+        }
+
+        return $options;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Block/Adminhtml/Types/Edit/GoogleShoppingForm.xml b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Block/Adminhtml/Types/Edit/GoogleShoppingForm.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fee98d9655b4b1e7550239681539af8145d158f1
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Block/Adminhtml/Types/Edit/GoogleShoppingForm.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <target_country>
+            <input>select</input>
+        </target_country>
+        <attribute_set_id>
+            <input>select</input>
+        </attribute_set_id>
+        <category>
+            <input>select</input>
+        </category>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Block/Adminhtml/Types/FormPageActions.php b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Block/Adminhtml/Types/FormPageActions.php
new file mode 100644
index 0000000000000000000000000000000000000000..db3f2cc136f1fc84d35b8ad3baa3af1498bd9908
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Block/Adminhtml/Types/FormPageActions.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GoogleShopping\Test\Block\Adminhtml\Types;
+
+use Magento\Backend\Test\Block\FormPageActions as AbstractFormPageActions;
+
+/**
+ * Class FormPageActions
+ * Page Actions for Google Shopping
+ */
+class FormPageActions extends AbstractFormPageActions
+{
+    /**
+     * "Save" button
+     *
+     * @var string
+     */
+    protected $saveButton = '#save_button';
+}
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Constraint/AssertProductAttributeAbsenceForAttributeMapping.php b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Constraint/AssertProductAttributeAbsenceForAttributeMapping.php
new file mode 100644
index 0000000000000000000000000000000000000000..a4b53e900627db3f8a121ba63ac6ee7b447e4aaa
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Constraint/AssertProductAttributeAbsenceForAttributeMapping.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GoogleShopping\Test\Constraint;
+
+use Mtf\Fixture\FixtureFactory;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Fixture\CatalogAttributeSet;
+use Magento\GoogleShopping\Test\Page\Adminhtml\GoogleShoppingTypesIndex;
+use Magento\GoogleShopping\Test\Page\Adminhtml\GoogleShoppingTypesNew;
+
+/**
+ * Class AssertProductAttributeAbsenceForAttributeMapping
+ * Assert that deleted attribute can't be mapped to Google Attribute
+ */
+class AssertProductAttributeAbsenceForAttributeMapping extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert that deleted attribute can't be mapped to Google Attribute (attribute doesn't appear in Attributes
+     * Mapping -> Google Content - Attributes after selecting attribute set)
+     *
+     * @param FixtureFactory $fixtureFactory
+     * @param CatalogAttributeSet $productTemplate
+     * @param GoogleShoppingTypesIndex $shoppingTypesIndex
+     * @param GoogleShoppingTypesNew $shoppingTypesNew
+     * @return void
+     */
+    public function processAssert(
+        FixtureFactory $fixtureFactory,
+        CatalogAttributeSet $productTemplate,
+        GoogleShoppingTypesIndex $shoppingTypesIndex,
+        GoogleShoppingTypesNew $shoppingTypesNew
+    ) {
+        $shoppingTypesIndex->open();
+        $shoppingTypesIndex->getPageActionsBlock()->addNew();
+
+        $shoppingAttributes = $fixtureFactory->createByCode(
+            'googleShoppingAttribute',
+            [
+                'dataSet' => 'default',
+                'data' => [
+                    'attribute_set_id' => ['attribute_set' => $productTemplate]
+                ],
+            ]
+        );
+
+        $shoppingTypesNew->getGoogleShoppingForm()->fill($shoppingAttributes);
+        $shoppingTypesNew->getGoogleShoppingForm()->clickAddNewAttribute();
+
+        $attributeCode = $productTemplate
+            ->getDataFieldConfig('assigned_attributes')['source']
+            ->getAttributes()[0]
+            ->getAttributeCode();
+
+        \PHPUnit_Framework_Assert::assertFalse(
+            $shoppingTypesNew->getGoogleShoppingForm()->findAttribute($attributeCode),
+            "Attribute " . $attributeCode . " is present in Attribute set mapping"
+        );
+    }
+
+    /**
+     * Text absent Product Attribute in Google Content Attribute Mapping
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return "Attribute is absent in Google Content Attribute Mapping.";
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Fixture/GoogleShoppingAttribute.php b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Fixture/GoogleShoppingAttribute.php
new file mode 100644
index 0000000000000000000000000000000000000000..8c4ee9b4598447229b69553da82a3702c7e353e8
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Fixture/GoogleShoppingAttribute.php
@@ -0,0 +1,106 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GoogleShopping\Test\Fixture;
+
+use Mtf\Fixture\InjectableFixture;
+
+/**
+ * Class GoogleShoppingAttribute
+ * Google Shopping Attribute fixture
+ *
+ */
+class GoogleShoppingAttribute extends InjectableFixture
+{
+    /**
+     * @var string
+     */
+    protected $repositoryClass = 'Magento\GoogleShopping\Test\Repository\GoogleShoppingAttribute';
+
+    // @codingStandardsIgnoreStart
+    /**
+     * @var string
+     */
+    protected $handlerInterface = 'Magento\GoogleShopping\Test\Handler\GoogleShoppingAttribute\GoogleShoppingAttributeInterface';
+    // @codingStandardsIgnoreEnd
+
+    protected $defaultDataSet = [
+        'target_country' => 'United States',
+        'attribute_set_id' => ['dataSet' => 'default'],
+        'category' => 'Apparel & Accessories',
+    ];
+
+    protected $type_id = [
+        'attribute_code' => 'type_id',
+        'backend_type' => 'int',
+        'is_required' => '1',
+        'default_value' => '',
+        'input' => '',
+    ];
+
+    protected $attribute_set_id = [
+        'attribute_code' => 'attribute_set_id',
+        'backend_type' => 'smallint',
+        'is_required' => '',
+        'default_value' => '',
+        'input' => '',
+        'source' => 'Magento\GoogleShopping\Test\Fixture\GoogleShoppingAttribute\AttributeSetId',
+    ];
+
+    protected $target_country = [
+        'attribute_code' => 'target_country',
+        'backend_type' => 'varchar',
+        'is_required' => '',
+        'default_value' => 'US',
+        'input' => '',
+    ];
+
+    protected $category = [
+        'attribute_code' => 'category',
+        'backend_type' => 'varchar',
+        'is_required' => '',
+        'default_value' => '',
+        'input' => '',
+    ];
+
+    public function getTypeId()
+    {
+        return $this->getData('type_id');
+    }
+
+    public function getAttributeSetId()
+    {
+        return $this->getData('attribute_set_id');
+    }
+
+    public function getTargetCountry()
+    {
+        return $this->getData('target_country');
+    }
+
+    public function getCategory()
+    {
+        return $this->getData('category');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Fixture/GoogleShoppingAttribute.xml b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Fixture/GoogleShoppingAttribute.xml
new file mode 100644
index 0000000000000000000000000000000000000000..71dfd2bc309f0c6140ecf140b3b859bd208fdc42
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Fixture/GoogleShoppingAttribute.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<fixture class="Magento\GoogleShopping\Test\Fixture\GoogleShoppingAttribute">
+    <module>Magento_GoogleShopping</module>
+    <type>flat</type>
+    <entity_type>googleshopping_types</entity_type>
+    <collection>Magento\GoogleShopping\Model\Resource\Attribute\Collection</collection>
+    <fields>
+        <type_id>
+            <attribute_code>type_id</attribute_code>
+            <backend_type>int</backend_type>
+            <is_required>1</is_required>
+            <default_value></default_value>
+            <input></input>
+        </type_id>
+        <attribute_set_id>
+            <attribute_code>attribute_set_id</attribute_code>
+            <backend_type>smallint</backend_type>
+            <source>Magento\GoogleShopping\Test\Fixture\GoogleShoppingAttribute\AttributeSetId</source>
+            <is_required></is_required>
+            <default_value></default_value>
+            <input></input>
+        </attribute_set_id>
+        <target_country>
+            <attribute_code>target_country</attribute_code>
+            <backend_type>varchar</backend_type>
+            <is_required></is_required>
+            <default_value>US</default_value>
+            <input></input>
+        </target_country>
+        <category>
+            <attribute_code>category</attribute_code>
+            <backend_type>varchar</backend_type>
+            <is_required></is_required>
+            <default_value></default_value>
+            <input></input>
+        </category>
+    </fields>
+    <repository_class>Magento\GoogleShopping\Test\Repository\GoogleShoppingAttribute</repository_class>
+    <handler_interface>Magento\GoogleShopping\Test\Handler\GoogleShoppingAttribute\GoogleShoppingAttributeInterface</handler_interface>
+</fixture>
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Fixture/GoogleShoppingAttribute/AttributeSetId.php b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Fixture/GoogleShoppingAttribute/AttributeSetId.php
new file mode 100644
index 0000000000000000000000000000000000000000..41cefa2cd7d49eb594c89d98707e146508a97de1
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Fixture/GoogleShoppingAttribute/AttributeSetId.php
@@ -0,0 +1,139 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GoogleShopping\Test\Fixture\GoogleShoppingAttribute;
+
+use Mtf\Fixture\FixtureInterface;
+use Mtf\Fixture\FixtureFactory;
+use Magento\Catalog\Test\Fixture\CatalogAttributeSet;
+
+/**
+ * Class AttributeSetId
+ * Prepare Attribute Set
+ *
+ *  Data keys:
+ *  - dataSet
+ *  - attribute_set
+ */
+class AttributeSetId implements FixtureInterface
+{
+    /**
+     * Data set configuration settings
+     *
+     * @var array
+     */
+    protected $params = [];
+
+    /**
+     * Attribute Set name
+     *
+     * @var string
+     */
+    protected $data;
+
+    /**
+     * Attribute Set fixture
+     *
+     * @var CatalogAttributeSet
+     */
+    protected $attributeSet;
+
+    /**
+     * @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'])) {
+            /** @var CatalogAttributeSet $attributeSet */
+            $attributeSet = $fixtureFactory->createByCode('catalogAttributeSet', ['dataSet' => $data['dataSet']]);
+            $this->prepareData($attributeSet);
+        }
+
+        if (isset($data['attribute_set']) && $data['attribute_set'] instanceof CatalogAttributeSet) {
+            $this->prepareData($data['attribute_set']);
+        }
+    }
+
+    /**
+     * Prepare Catalog Attribute Set data
+     *
+     * @param CatalogAttributeSet $attributeSet
+     * @return void
+     */
+    protected function prepareData(CatalogAttributeSet $attributeSet)
+    {
+        if (!$attributeSet->hasData('attribute_set_id')) {
+            $attributeSet->persist();
+        }
+
+        $this->data = $attributeSet->getAttributeSetName();
+        $this->attributeSet = $attributeSet;
+    }
+
+    /**
+     * Persist attribute options
+     *
+     * @return void
+     */
+    public function persist()
+    {
+        //
+    }
+
+    /**
+     * Return prepared data set
+     *
+     * @param string|null $key
+     * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function getData($key = null)
+    {
+        return $this->data;
+    }
+
+    /**
+     * Return Attribute Set fixture
+     *
+     * @return CatalogAttributeSet
+     */
+    public function getAttributeSet()
+    {
+        return $this->attributeSet;
+    }
+
+    /**
+     * Return data set configuration settings
+     *
+     * @return array
+     */
+    public function getDataConfig()
+    {
+        return $this->params;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Page/Adminhtml/GoogleShoppingTypesIndex.php b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Page/Adminhtml/GoogleShoppingTypesIndex.php
new file mode 100644
index 0000000000000000000000000000000000000000..eeec2cdc9df6a639aa0a4b7539cd393f96aa147a
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Page/Adminhtml/GoogleShoppingTypesIndex.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GoogleShopping\Test\Page\Adminhtml;
+
+use Mtf\Page\BackendPage;
+
+/**
+ * Class GoogleShoppingTypesIndex
+ */
+class GoogleShoppingTypesIndex extends BackendPage
+{
+    const MCA = 'admin/googleshopping_types/index';
+
+    protected $_blocks = [
+        'pageActionsBlock' => [
+            'name' => 'pageActionsBlock',
+            'class' => 'Magento\Backend\Test\Block\GridPageActions',
+            'locator' => '.page-main-actions',
+            'strategy' => 'css selector',
+        ],
+        'grid' => [
+            'name' => 'grid',
+            'class' => 'Magento\Backend\Test\Block\Widget\Grid',
+            'locator' => '#types_grid',
+            'strategy' => 'css selector',
+        ],
+    ];
+
+    /**
+     * @return \Magento\Backend\Test\Block\GridPageActions
+     */
+    public function getPageActionsBlock()
+    {
+        return $this->getBlockInstance('pageActionsBlock');
+    }
+
+    /**
+     * @return \Magento\Backend\Test\Block\Widget\Grid
+     */
+    public function getGrid()
+    {
+        return $this->getBlockInstance('grid');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Page/Adminhtml/GoogleShoppingTypesIndex.xml b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Page/Adminhtml/GoogleShoppingTypesIndex.xml
new file mode 100644
index 0000000000000000000000000000000000000000..60f2a3b0f88986b389b4518a98c10c3ab9b1494f
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Page/Adminhtml/GoogleShoppingTypesIndex.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<page mca="admin/googleshopping_types/index" >
+    <block>
+        <name>pageActionsBlock</name>
+        <class>Magento\Backend\Test\Block\GridPageActions</class>
+        <locator>.page-main-actions</locator>
+        <strategy>css selector</strategy>
+    </block>
+    <block>
+        <name>grid</name>
+        <class>Magento\Backend\Test\Block\Widget\Grid</class>
+        <locator>#types_grid</locator>
+        <strategy>css selector</strategy>
+    </block>
+</page>
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Page/Adminhtml/GoogleShoppingTypesNew.php b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Page/Adminhtml/GoogleShoppingTypesNew.php
new file mode 100644
index 0000000000000000000000000000000000000000..b85bfa2a43923b9fc56ca3631275948ba6277777
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Page/Adminhtml/GoogleShoppingTypesNew.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GoogleShopping\Test\Page\Adminhtml;
+
+use Mtf\Page\BackendPage;
+
+/**
+ * Class GoogleShoppingTypesNew
+ */
+class GoogleShoppingTypesNew extends BackendPage
+{
+    const MCA = 'admin/googleshopping_types/new';
+
+    protected $_blocks = [
+        'pageActions' => [
+            'name' => 'pageActions',
+            'class' => 'Magento\GoogleShopping\Test\Block\Adminhtml\Types\FormPageActions',
+            'locator' => '.page-main-actions',
+            'strategy' => 'css selector',
+        ],
+        'googleShoppingForm' => [
+            'name' => 'googleShoppingForm',
+            'class' => 'Magento\GoogleShopping\Test\Block\Adminhtml\Types\Edit\GoogleShoppingForm',
+            'locator' => '#edit_form',
+            'strategy' => 'css selector',
+        ],
+    ];
+
+    /**
+     * @return \Magento\GoogleShopping\Test\Block\Adminhtml\Types\FormPageActions
+     */
+    public function getPageActions()
+    {
+        return $this->getBlockInstance('pageActions');
+    }
+
+    /**
+     * @return \Magento\GoogleShopping\Test\Block\Adminhtml\Types\Edit\GoogleShoppingForm
+     */
+    public function getGoogleShoppingForm()
+    {
+        return $this->getBlockInstance('googleShoppingForm');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Page/Adminhtml/GoogleShoppingTypesNew.xml b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Page/Adminhtml/GoogleShoppingTypesNew.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ede1f39f873f65875af34fe309409d0a004cf44e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Page/Adminhtml/GoogleShoppingTypesNew.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<page mca="admin/googleshopping_types/new" >
+    <block>
+        <name>pageActions</name>
+        <class>Magento\GoogleShopping\Test\Block\Adminhtml\Types\FormPageActions</class>
+        <locator>.page-main-actions</locator>
+        <strategy>css selector</strategy>
+    </block>
+    <block>
+        <name>googleShoppingForm</name>
+        <class>Magento\GoogleShopping\Test\Block\Adminhtml\Types\Edit\GoogleShoppingForm</class>
+        <locator>#edit_form</locator>
+        <strategy>css selector</strategy>
+    </block>
+</page>
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Repository/GoogleShoppingAttribute.php b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Repository/GoogleShoppingAttribute.php
new file mode 100644
index 0000000000000000000000000000000000000000..ad0f63787acb69beb376f063ad35844c51c1ae7c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/Repository/GoogleShoppingAttribute.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GoogleShopping\Test\Repository;
+
+use Mtf\Repository\AbstractRepository;
+
+/**
+ * Class GoogleShoppingAttribute
+ * Data for creation Google Shopping Attribute
+ */
+class GoogleShoppingAttribute extends AbstractRepository
+{
+    /**
+     * Construct
+     *
+     * @param array $defaultConfig
+     * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function __construct(array $defaultConfig = [], array $defaultData = [])
+    {
+        $this->_data['default'] = [
+            'target_country' => 'United States',
+            'attribute_set_id' => ['dataSet' => 'default'],
+            'category' => 'Apparel & Accessories',
+        ];
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/etc/global/constraint.xml b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/etc/global/constraint.xml
new file mode 100644
index 0000000000000000000000000000000000000000..98f2758d87a6918ff56d1ab03e14e96779489b65
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/etc/global/constraint.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<constraint>
+    <assertProductAttributeAbsenceForAttributeMapping module="Magento_GoogleShopping">
+        <severeness>low</severeness>
+    </assertProductAttributeAbsenceForAttributeMapping>
+</constraint>
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/etc/global/fixture.xml b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/etc/global/fixture.xml
new file mode 100644
index 0000000000000000000000000000000000000000..360dd77494cf29a0517da551238287bf6bae45fa
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/etc/global/fixture.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<fixture>
+    <googleShoppingAttribute module="Magento_GoogleShopping">
+        <type>flat</type>
+        <entity_type>googleshopping_types</entity_type>
+        <collection>Magento\GoogleShopping\Model\Resource\Attribute\Collection</collection>
+    </googleShoppingAttribute>
+</fixture>
diff --git a/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/etc/global/page.xml b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/etc/global/page.xml
new file mode 100644
index 0000000000000000000000000000000000000000..11e855db77eb18dba256ddc7d1ebd95572c03ba6
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GoogleShopping/Test/etc/global/page.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<page>
+    <googleShoppingTypesIndex>
+        <mca>admin/googleshopping_types/index</mca>
+        <area>adminhtml</area>
+        <class>Magento\GoogleShopping\Test\Page\Adminhtml\GoogleShoppingTypesIndex</class>
+    </googleShoppingTypesIndex>
+    <googleShoppingTypesNew>
+        <mca>admin/googleshopping_types/new</mca>
+        <area>adminhtml</area>
+        <class>Magento\GoogleShopping\Test\Page\Adminhtml\GoogleShoppingTypesNew</class>
+    </googleShoppingTypesNew>
+</page>
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts.php
new file mode 100644
index 0000000000000000000000000000000000000000..265f133d48040bec7b42adcae5f053edd4a4a5ac
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts.php
@@ -0,0 +1,123 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GroupedProduct\Test\Block\Adminhtml\Product\Grouped;
+
+use Mtf\Client\Element;
+use Mtf\Client\Element\Locator;
+use Magento\Backend\Test\Block\Widget\Tab;
+
+/**
+ * Class AssociatedProducts
+ * Grouped products tab
+ */
+class AssociatedProducts extends Tab
+{
+    /**
+     * 'Create New Option' button
+     *
+     * @var string
+     */
+    protected $addNewOption = '#grouped-product-container>button';
+
+    /**
+     * Associated products grid locator
+     *
+     * @var string
+     */
+    protected $productSearchGrid = "./ancestor::body//div[div[contains(@data-role,'add-product-dialog')]]";
+
+    /**
+     * Associated products list block
+     *
+     * @var string
+     */
+    protected $associatedProductsBlock = '[data-role=grouped-product-grid]';
+
+    /**
+     * Get search grid
+     *
+     * @return AssociatedProducts\Search\Grid
+     */
+    protected function getSearchGridBlock()
+    {
+        return $this->blockFactory->create(
+            'Magento\GroupedProduct\Test\Block\Adminhtml\Product\Grouped\AssociatedProducts\Search\Grid',
+            ['element' => $this->_rootElement->find($this->productSearchGrid, Locator::SELECTOR_XPATH)]
+        );
+    }
+
+    /**
+     * Get associated products list block
+     *
+     * @return AssociatedProducts\ListAssociatedProducts
+     */
+    protected function getListAssociatedProductsBlock()
+    {
+        return $this->blockFactory->create(
+            'Magento\GroupedProduct\Test\Block\Adminhtml\Product\Grouped\AssociatedProducts\ListAssociatedProducts',
+            ['element' => $this->_rootElement->find($this->associatedProductsBlock)]
+        );
+    }
+
+    /**
+     * Fill data to fields on tab
+     *
+     * @param array $fields
+     * @param Element|null $element
+     * @return $this
+     */
+    public function fillFormTab(array $fields, Element $element = null)
+    {
+        if (isset($fields['associated'])) {
+            foreach ($fields['associated']['value']['assigned_products'] as $key => $groupedProduct) {
+                $element->find($this->addNewOption)->click();
+                $searchBlock = $this->getSearchGridBlock();
+                $searchBlock->searchAndSelect(['name' => $groupedProduct['name']]);
+                $searchBlock->addProducts();
+                $this->getListAssociatedProductsBlock()->fillProductOptions($groupedProduct, ($key + 1));
+            }
+        }
+        return $this;
+    }
+
+    /**
+     * Get data to fields on group tab
+     *
+     * @param array|null $fields
+     * @param Element|null $element
+     * @return array
+     */
+    public function getDataFormTab($fields = null, Element $element = null)
+    {
+        $newFields = [];
+        if (isset($fields['associated'])) {
+            foreach ($fields['associated']['value']['assigned_products'] as $key => $groupedProduct) {
+                $newFields['associated']['assigned_products'][$key] = $this->getListAssociatedProductsBlock()
+                    ->getProductOptions($groupedProduct, ($key + 1));
+            }
+        }
+        return $newFields;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/ListAssociatedProducts.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/ListAssociatedProducts.php
new file mode 100644
index 0000000000000000000000000000000000000000..8a7889aaa7dc7632880d24b5dd4b8cc6726d3f85
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/ListAssociatedProducts.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GroupedProduct\Test\Block\Adminhtml\Product\Grouped\AssociatedProducts;
+
+use Mtf\Block\Form;
+use Mtf\Client\Element;
+use Mtf\Client\Element\Locator;
+
+/**
+ * Class ListAssociatedProducts
+ * List associated products on the page
+ */
+class ListAssociatedProducts extends Form
+{
+    /**
+     * Selector with item product
+     *
+     * @var string
+     */
+    protected $itemProduct = '//tr[@data-role="row"][%d]';
+
+    /**
+     * Getting block products
+     *
+     * @param string $index
+     * @return ListAssociatedProducts\Product
+     */
+    private function getProductBlock($index)
+    {
+        $className = 'Magento\GroupedProduct\Test\Block\Adminhtml\Product\\' .
+            'Grouped\AssociatedProducts\ListAssociatedProducts\Product';
+        return $this->blockFactory->create(
+            $className,
+            ['element' => $this->_rootElement->find(sprintf($this->itemProduct, $index), Locator::SELECTOR_XPATH)]
+        );
+    }
+
+    /**
+     * Filling options products
+     *
+     * @param array $data
+     * @param int $index
+     * @return void
+     */
+    public function fillProductOptions(array $data, $index)
+    {
+        $this->getProductBlock($index)->fillOption($data);
+    }
+
+    /**
+     * Get options products
+     *
+     * @param array $data
+     * @param int $index
+     * @return array
+     */
+    public function getProductOptions(array $data, $index)
+    {
+        return $this->getProductBlock($index)->getOption($data);
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/ListAssociatedProducts/Product.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/ListAssociatedProducts/Product.php
new file mode 100644
index 0000000000000000000000000000000000000000..c92fdd60b4d13bd0510baaee822885649dab6e6f
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/ListAssociatedProducts/Product.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GroupedProduct\Test\Block\Adminhtml\Product\Grouped\AssociatedProducts\ListAssociatedProducts;
+
+use Mtf\Block\Form;
+
+/**
+ * Class Product
+ * Assigned product row to grouped option
+ */
+class Product extends Form
+{
+    /**
+     * Fill product options
+     *
+     * @param string $qtyValue
+     * @return void
+     */
+    public function fillOption($qtyValue)
+    {
+        $mapping = $this->dataMapping($qtyValue);
+        $this->_fill($mapping);
+    }
+
+    /**
+     * Get product options
+     *
+     * @param array $fields
+     * @return array
+     */
+    public function getOption(array $fields)
+    {
+        $mapping = $this->dataMapping($fields);
+        $newFields = $this->_getData($mapping);
+        $newFields['name'] = $this->_rootElement->find('td.col-name')->getText();
+        return $newFields;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/ListAssociatedProducts/Product.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/ListAssociatedProducts/Product.xml
new file mode 100644
index 0000000000000000000000000000000000000000..909234b8b1fa95ecddc864cd6d3bb36e5357a881
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/ListAssociatedProducts/Product.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<mapping strict="1">
+    <fields>
+        <qty>
+            <selector>[name$='[qty]']</selector>
+        </qty>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/Search/Grid.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/Search/Grid.php
new file mode 100644
index 0000000000000000000000000000000000000000..ee9598ef65b80c87561dd644fc59ff1488d4952f
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/Search/Grid.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GroupedProduct\Test\Block\Adminhtml\Product\Grouped\AssociatedProducts\Search;
+
+use Mtf\Client\Element;
+use Magento\Backend\Test\Block\Widget\Grid as GridInterface;
+
+/**
+ * Class Grid
+ * 'Add Products to Grouped product list' grid
+ */
+class Grid extends GridInterface
+{
+    /**
+     * 'Add Selected Products' button
+     *
+     * @var string
+     */
+    protected $addProducts = 'button.add';
+
+    /**
+     * Filters array mapping
+     *
+     * @var array
+     */
+    protected $filters = [
+        'name' => [
+            'selector' => '#grouped_grid_popup_filter_name'
+        ]
+    ];
+
+    /**
+     * An element locator which allows to select entities in grid
+     *
+     * @var string
+     */
+    protected $selectItem = '[data-column=entity_id] input';
+
+    /**
+     * Press 'Add Selected Products' button
+     *
+     * @return void
+     */
+    public function addProducts()
+    {
+        $this->_rootElement->find($this->addProducts)->click();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/ProductForm.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/ProductForm.xml
new file mode 100644
index 0000000000000000000000000000000000000000..75d062205693372768fb598010fb7f9980a2d7a9
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/ProductForm.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<tabs>
+    <grouped>
+        <class>\Magento\GroupedProduct\Test\Block\Adminhtml\Product\Grouped\AssociatedProducts</class>
+        <selector>#product_info_tabs_product-details</selector>
+        <strategy>css selector</strategy>
+    </grouped>
+</tabs>
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View.php
new file mode 100755
index 0000000000000000000000000000000000000000..3c0134fa4cfe95bca48430e40d24ed1ee629d99e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GroupedProduct\Test\Block\Catalog\Product;
+
+use Magento\Catalog\Test\Block\Product\View as ParentView;
+
+/**
+ * Class View
+ * Grouped product view block on the product page
+ */
+class View extends ParentView
+{
+    /**
+     * Block grouped product
+     *
+     * @var string
+     */
+    protected $groupedProductBlock = '.wrapper.table.grouped';
+
+    /**
+     * This member holds the class name of the tier price block.
+     *
+     * @var string
+     */
+    protected $formatTierPrice = "//tbody[%row-number%]//ul[contains(@class,'tier')]//*[@class='item'][%line-number%]";
+
+    /**
+     * This member holds the class name of the special price block.
+     *
+     * @var string
+     */
+    protected $formatSpecialPrice = ".product-info-main tr:nth-child(%row-number%) .price-box";
+
+    /**
+     * Get grouped product block
+     *
+     * @return \Magento\GroupedProduct\Test\Block\Catalog\Product\View\Type\Grouped
+     */
+    public function getGroupedProductBlock()
+    {
+        return $this->blockFactory->create(
+            'Magento\GroupedProduct\Test\Block\Catalog\Product\View\Type\Grouped',
+            [
+                'element' => $this->_rootElement->find($this->groupedProductBlock)
+            ]
+        );
+    }
+
+    /**
+     * Change tier price selector
+     *
+     * @param int $index
+     * @return void
+     */
+    public function itemTierPriceProductBlock($index)
+    {
+        $this->tierPricesSelector = str_replace('%row-number%', $index, $this->formatTierPrice);
+    }
+
+    /**
+     * Change tier price selector
+     *
+     * @param int $index
+     * @return void
+     */
+    public function itemPriceProductBlock($index)
+    {
+        $this->priceBlock = str_replace('%row-number%', $index, $this->formatSpecialPrice);
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View/Type/Grouped.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View/Type/Grouped.php
new file mode 100644
index 0000000000000000000000000000000000000000..ce889be6f7368673e68fb0c29a39ec7374e78ab0
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View/Type/Grouped.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GroupedProduct\Test\Block\Catalog\Product\View\Type;
+
+use Mtf\Block\Block;
+
+/**
+ * Class Grouped
+ * Grouped product blocks on frontend
+ */
+class Grouped extends Block
+{
+    /**
+     * Selector qty for sub product
+     *
+     * @var string
+     */
+    protected $qtySubProduct = '[name="super_group[%d]"]';
+
+    /**
+     * Get qty for subProduct
+     *
+     * @param int $subProductId
+     * @return string
+     */
+    public function getQty($subProductId)
+    {
+        return $this->_rootElement->find(sprintf($this->qtySubProduct, $subProductId))->getValue();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AbstractAssertPriceOnGroupedProductPage.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AbstractAssertPriceOnGroupedProductPage.php
new file mode 100644
index 0000000000000000000000000000000000000000..61efaeeb4e23e23047c937db44c7494e005e9900
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AbstractAssertPriceOnGroupedProductPage.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GroupedProduct\Test\Constraint;
+
+use Mtf\Fixture\InjectableFixture;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\GroupedProduct\Test\Fixture\CatalogProductGrouped;
+use Magento\GroupedProduct\Test\Page\Product\CatalogProductView;
+use Magento\Catalog\Test\Constraint\AssertPriceOnProductPageInterface;
+
+/**
+ * Class AbstractAssertPriceOnGroupedProductPage
+ * Assert that displayed price on grouped product page equals passed from fixture
+ */
+abstract class AbstractAssertPriceOnGroupedProductPage extends AbstractConstraint
+{
+    /**
+     * Format error message
+     *
+     * @var string
+     */
+    protected $errorMessage;
+
+    /**
+     * Successful message
+     *
+     * @var string
+     */
+    protected $successfulMessage;
+
+    /**
+     * Verify product price on grouped product view page
+     *
+     * @param CatalogProductGrouped $product
+     * @param CatalogProductView $catalogProductView
+     * @param AssertPriceOnProductPageInterface $object
+     * @param string $typePrice [optional]
+     * @return bool|string
+     */
+    protected function processAssertPrice(
+        CatalogProductGrouped $product,
+        CatalogProductView $catalogProductView,
+        AssertPriceOnProductPageInterface $object,
+        $typePrice = ''
+    ) {
+        $catalogProductView->init($product);
+        $catalogProductView->open();
+
+        $groupedData = $product->getAssociated();
+        /** @var InjectableFixture $subProduct */
+        foreach ($groupedData['products'] as $key => $subProduct) {
+            //Process assertions
+            $catalogProductView->getGroupedViewBlock()
+                ->{'item' . $typePrice . 'PriceProductBlock'}(++$key);
+            $object->setErrorMessage(sprintf($this->errorMessage, $subProduct->getData('name')));
+            $object->assertPrice($subProduct, $catalogProductView, 'Grouped');
+        }
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return $this->successfulMessage;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertGroupedPriceOnGroupedProductPage.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertGroupedPriceOnGroupedProductPage.php
new file mode 100644
index 0000000000000000000000000000000000000000..246a06f43ee8da3199d4b140e514e2cc340b44dd
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertGroupedPriceOnGroupedProductPage.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GroupedProduct\Test\Constraint;
+
+use Magento\GroupedProduct\Test\Fixture\CatalogProductGrouped;
+use Magento\GroupedProduct\Test\Page\Product\CatalogProductView;
+use Magento\Catalog\Test\Constraint\AssertProductGroupedPriceOnProductPage;
+
+/**
+ * Class AssertGroupedPriceOnGroupedProductPage
+ */
+class AssertGroupedPriceOnGroupedProductPage extends AbstractAssertPriceOnGroupedProductPage
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Format error message
+     *
+     * @var string
+     */
+    protected $errorMessage = 'This "%s" product\'s grouped price on product page NOT equals passed from fixture.';
+
+    /**
+     * Successful message
+     *
+     * @var string
+     */
+    protected $successfulMessage = 'Displayed grouped price on grouped product page equals to passed from a fixture.';
+
+    /**
+     * Assert that displayed grouped price on grouped product page equals passed from fixture
+     *
+     * @param CatalogProductView $catalogProductView
+     * @param CatalogProductGrouped $product
+     * @param AssertProductGroupedPriceOnProductPage $groupedPrice
+     * @return void
+     */
+    public function processAssert(
+        CatalogProductView $catalogProductView,
+        CatalogProductGrouped $product,
+        AssertProductGroupedPriceOnProductPage $groupedPrice
+    ) {
+        $this->processAssertPrice($product, $catalogProductView, $groupedPrice);
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertGroupedProductForm.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertGroupedProductForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..b85ac418f65fcbe4881b5c0719c54165913b78b2
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertGroupedProductForm.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GroupedProduct\Test\Constraint;
+
+use Mtf\Fixture\FixtureInterface;
+use Magento\Catalog\Test\Constraint\AssertProductForm;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+
+/**
+ * Class AssertGroupedProductForm
+ */
+class AssertGroupedProductForm extends AssertProductForm
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert form data equals fixture data
+     *
+     * @param FixtureInterface $product
+     * @param CatalogProductIndex $productGrid
+     * @param CatalogProductEdit $productPage
+     * @return void
+     */
+    public function processAssert(
+        FixtureInterface $product,
+        CatalogProductIndex $productGrid,
+        CatalogProductEdit $productPage
+    ) {
+        $filter = ['sku' => $product->getSku()];
+        $productGrid->open()->getProductGrid()->searchAndOpen($filter);
+        $fieldsForm = $productPage->getForm()->getData($product);
+        $fieldsFixture = $this->prepareFixtureData($product->getData());
+        $fieldsFixture['associated'] = $this->prepareGroupedOptions($fieldsFixture['associated']);
+
+        $errors = $this->verifyData($fieldsFixture, $fieldsForm);
+        \PHPUnit_Framework_Assert::assertEmpty($errors, $errors);
+    }
+
+    /**
+     * Prepare Grouped Options array from preset
+     *
+     * @param array $fields
+     * @return array
+     */
+    protected function prepareGroupedOptions(array $fields)
+    {
+        $result = [];
+        foreach ($fields['assigned_products'] as $key => $item) {
+            $result['assigned_products'][$key]['name'] = $item['name'];
+            $result['assigned_products'][$key]['qty'] = $item['qty'];
+        }
+
+        return $result;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertGroupedProductsDefaultQty.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertGroupedProductsDefaultQty.php
new file mode 100644
index 0000000000000000000000000000000000000000..06e42f6130f991fbd91b10f687e2a358c189ac44
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertGroupedProductsDefaultQty.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GroupedProduct\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\GroupedProduct\Test\Page\Product\CatalogProductView;
+use Magento\GroupedProduct\Test\Fixture\CatalogProductGrouped;
+
+/**
+ * Class AssertGroupedProductsDefaultQty
+ */
+class AssertGroupedProductsDefaultQty extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert that default qty for sub products in grouped product displays according to dataset on product page.
+     *
+     * @param CatalogProductView $groupedProductView
+     * @param CatalogProductGrouped $product
+     * @return void
+     */
+    public function processAssert(CatalogProductView $groupedProductView, CatalogProductGrouped $product)
+    {
+        $groupedProductView->init($product);
+        $groupedProductView->open();
+        $groupedBlock = $groupedProductView->getGroupedViewBlock()->getGroupedProductBlock();
+        $groupedProduct = $product->getData();
+
+        foreach ($groupedProduct['associated']['assigned_products'] as $item) {
+            \PHPUnit_Framework_Assert::assertEquals(
+                $groupedBlock->getQty($item['id']),
+                $item['qty'],
+                'Default qty for sub product "' . $item['name'] . '" in grouped product according to dataset.'
+            );
+        }
+    }
+
+    /**
+     * Text of Visible in grouped assert for default qty for sub products
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Default qty for sub products in grouped product displays according to dataset on product page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertSpecialPriceOnGroupedProductPage.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertSpecialPriceOnGroupedProductPage.php
new file mode 100644
index 0000000000000000000000000000000000000000..35c2f9babbd39d80dfea4527a7192133940900cd
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertSpecialPriceOnGroupedProductPage.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GroupedProduct\Test\Constraint;
+
+use Magento\GroupedProduct\Test\Fixture\CatalogProductGrouped;
+use Magento\GroupedProduct\Test\Page\Product\CatalogProductView;
+use Magento\Catalog\Test\Constraint\AssertProductSpecialPriceOnProductPage;
+
+/**
+ * Class AssertSpecialPriceOnGroupedProductPage
+ */
+class AssertSpecialPriceOnGroupedProductPage extends AbstractAssertPriceOnGroupedProductPage
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Format error message
+     *
+     * @var string
+     */
+    protected $errorMessage = 'This "%s" product\'s special price on product page NOT equals passed from fixture.';
+
+    /**
+     * Successful message
+     *
+     * @var string
+     */
+    protected $successfulMessage = 'Special price on grouped product page equals passed from fixture.';
+
+    /**
+     * Assert that displayed grouped price on grouped product page equals passed from fixture
+     *
+     * @param CatalogProductView $catalogProductView
+     * @param CatalogProductGrouped $product
+     * @param AssertProductSpecialPriceOnProductPage $specialPrice
+     * @return void
+     */
+    public function processAssert(
+        CatalogProductView $catalogProductView,
+        CatalogProductGrouped $product,
+        AssertProductSpecialPriceOnProductPage $specialPrice
+    ) {
+        $this->processAssertPrice($product, $catalogProductView, $specialPrice);
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertTierPriceOnGroupedProductPage.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertTierPriceOnGroupedProductPage.php
new file mode 100644
index 0000000000000000000000000000000000000000..315be6c14d9d25e4668ad1033348db5a6f08385c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertTierPriceOnGroupedProductPage.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GroupedProduct\Test\Constraint;
+
+use Magento\GroupedProduct\Test\Fixture\CatalogProductGrouped;
+use Magento\GroupedProduct\Test\Page\Product\CatalogProductView;
+use Magento\Catalog\Test\Constraint\AssertProductTierPriceOnProductPage;
+
+/**
+ * Class AssertTierPriceOnGroupedProductPage
+ */
+class AssertTierPriceOnGroupedProductPage extends AbstractAssertPriceOnGroupedProductPage
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Format error message
+     *
+     * @var string
+     */
+    protected $errorMessage = 'For "%s" Product tier price on product page is not correct.';
+
+    /**
+     * Successful message
+     *
+     * @var string
+     */
+    protected $successfulMessage = 'Tier price is displayed on the grouped product page.';
+
+    /**
+     * Assert that displayed grouped price on grouped product page equals passed from fixture
+     *
+     * @param CatalogProductView $catalogProductView
+     * @param CatalogProductGrouped $product
+     * @param AssertProductTierPriceOnProductPage $tierPrice
+     * @return void
+     */
+    public function processAssert(
+        CatalogProductView $catalogProductView,
+        CatalogProductGrouped $product,
+        AssertProductTierPriceOnProductPage $tierPrice
+    ) {
+        $this->processAssertPrice($product, $catalogProductView, $tierPrice, 'Tier');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/CatalogProductGrouped.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/CatalogProductGrouped.php
index 7944dfd15aa15c6a232fb517336e56c215e09a5e..8137dfa827a54a2a058091f6a65787f95bb36186 100644
--- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/CatalogProductGrouped.php
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/CatalogProductGrouped.php
@@ -89,7 +89,6 @@ class CatalogProductGrouped extends InjectableFixture
         if (!isset($this->data['url_key']) && isset($this->data['name'])) {
             $this->data['url_key'] = trim(strtolower(preg_replace('#[^0-9a-z%]+#i', '-', $this->data['name'])), '-');
         }
-
     }
 
     protected $dataConfig = [
@@ -103,7 +102,6 @@ class CatalogProductGrouped extends InjectableFixture
     protected $defaultDataSet = [
         'name' => 'GroupedProduct_%isolation%',
         'sku' => 'GroupedProduct_%isolation%',
-        'price' => '100',
         'tax_class' => 'Taxable Goods',
         'description' => 'This is description for grouped product',
         'short_description' => 'This is short description for grouped product',
@@ -119,7 +117,7 @@ class CatalogProductGrouped extends InjectableFixture
         'is_required' => '0',
         'default_value' => '',
         'input' => 'text',
-        'source' => 'Magento\Catalog\Test\Fixture\CatalogProductSimple\CategoryIds'
+        'source' => 'Magento\Catalog\Test\Fixture\CatalogProductSimple\CategoryIds',
     ];
 
     protected $country_of_manufacture = [
@@ -477,7 +475,14 @@ class CatalogProductGrouped extends InjectableFixture
     protected $website_ids = [
         'attribute_code' => 'website_ids',
         'backend_type' => 'virtual',
-        'default_value' => 'Main Website',
+        'default_value' => ['Main Website'],
+        'group' => 'websites',
+    ];
+
+    protected $price = [
+        'attribute_code' => 'price',
+        'backend_type' => 'virtual',
+        'source' => 'Magento\GroupedProduct\Test\Fixture\CatalogProductGrouped\Price',
     ];
 
     public function getCategoryIds()
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/CatalogProductGrouped.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/CatalogProductGrouped.xml
index 95e73b5137daf9676adcc83c527b5c9b5e66f461..4bd9649b5cd262e88d9d4281d9e52aa9c987e47c 100644
--- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/CatalogProductGrouped.xml
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/CatalogProductGrouped.xml
@@ -343,7 +343,13 @@
             <attribute_code>website_ids</attribute_code>
             <backend_type>virtual</backend_type>
             <default_value>Main Website</default_value>
+            <group>websites</group>
         </website_ids>
+        <price>
+            <attribute_code>price</attribute_code>
+            <backend_type>virtual</backend_type>
+            <source>'Magento\Catalog\Test\Fixture\CatalogProductSimple\Price</source>
+        </price>
     </fields>
     <data_set>
         <sku></sku>
@@ -360,5 +366,6 @@
         <input_prefix>product</input_prefix>
     </data_config>
     <repository_class>Magento\Catalog\Test\Repository\CatalogProductGrouped</repository_class>
-    <handler_interface>Magento\Catalog\Test\Handler\CatalogProductGrouped\CatalogProductGroupedInterface</handler_interface>
+    <handler_interface>Magento\Catalog\Test\Handler\CatalogProductGrouped\CatalogProductGroupedInterface
+    </handler_interface>
 </fixture>
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/CatalogProductGrouped/Associated.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/CatalogProductGrouped/Associated.php
index 7f6acc8d1d50a6bac93a87bdf7c41f2b9e3abb09..9f0b5ff31f0c41f1d8ef0b8f692501f073639d76 100644
--- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/CatalogProductGrouped/Associated.php
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/CatalogProductGrouped/Associated.php
@@ -72,6 +72,9 @@ class Associated implements FixtureInterface
         }
 
         if (!empty($this->data['products'])) {
+            $this->data['products'] = is_array($this->data['products'])
+                ? $this->data['products']
+                : explode(',', $this->data['products']);
             foreach ($this->data['products'] as $key => $product) {
                 list($fixture, $dataSet) = explode('::', $product);
                 /** @var $productFixture InjectableFixture */
@@ -85,6 +88,7 @@ class Associated implements FixtureInterface
 
             $assignedProducts = & $this->data['assigned_products'];
             foreach (array_keys($assignedProducts) as $key) {
+                $assignedProducts[$key]['name'] = $this->data['products'][$key]->getName();
                 $assignedProducts[$key]['id'] = $this->data['products'][$key]->getId();
                 $assignedProducts[$key]['position'] = $key + 1;
             }
@@ -137,14 +141,16 @@ class Associated implements FixtureInterface
                 'assigned_products' => [
                     [
                         'id' => '%id%',
+                        'name' => '%item1_simple::getProductName%',
                         'position' => '%position%',
-                        'qty' => 5
+                        'qty' => 1,
                     ],
                     [
                         'id' => '%id%',
+                        'name' => '%item1_simple::getProductName%',
                         'position' => '%position%',
-                        'qty' => 6
-                    ]
+                        'qty' => 2,
+                    ],
                 ],
                 'products' => [
                     'catalogProductSimple::default',
@@ -155,14 +161,16 @@ class Associated implements FixtureInterface
                 'assigned_products' => [
                     [
                         'id' => '%id%',
+                        'name' => '%item1_virtual::getProductName%',
                         'position' => '%position%',
-                        'qty' => 5
+                        'qty' => 1,
                     ],
                     [
                         'id' => '%id%',
+                        'name' => '%item1_virtual::getProductName%',
                         'position' => '%position%',
-                        'qty' => 6
-                    ]
+                        'qty' => 2,
+                    ],
                 ],
                 'products' => [
                     'catalogProductVirtual::default',
@@ -170,11 +178,9 @@ class Associated implements FixtureInterface
                 ],
             ]
         ];
-
         if (!isset($presets[$name])) {
             return null;
         }
-
         return $presets[$name];
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/CatalogProductGrouped/Price.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/CatalogProductGrouped/Price.php
new file mode 100644
index 0000000000000000000000000000000000000000..f045ffde4d5b10aa3079005270d0e786bd269800
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/CatalogProductGrouped/Price.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GroupedProduct\Test\Fixture\CatalogProductGrouped;
+
+use Mtf\Fixture\FixtureInterface;
+use Magento\Catalog\Test\Fixture\CatalogProductSimple\Price as ParentPrice;
+
+/**
+ * Class Price
+ *
+ * Data keys:
+ *  - preset (Price verification preset name)
+ *  - value (Price value)
+ */
+class Price extends ParentPrice implements FixtureInterface
+{
+    /**
+     * Preset for price
+     *
+     * @return array|null
+     */
+    public function getPreset()
+    {
+        $presets = [
+            'starting-560' => [
+                'compare_price' => [
+                    'price_starting' => '560.00',
+                ]
+            ],
+        ];
+        if (!isset($presets[$this->currentPreset])) {
+            return null;
+        }
+        return $presets[$this->currentPreset];
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Page/Product/CatalogProductView.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Page/Product/CatalogProductView.php
new file mode 100755
index 0000000000000000000000000000000000000000..d0bf56970017ab5a2c1db5998830ea46ee7a6a3f
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Page/Product/CatalogProductView.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GroupedProduct\Test\Page\Product;
+
+use Magento\Catalog\Test\Page\Product\CatalogProductView as ParentCatalogProductView;
+
+/**
+ * Class CatalogProductView
+ * Frontend grouped product view page
+ */
+class CatalogProductView extends ParentCatalogProductView
+{
+    const MCA = 'grouped/catalog/product/view';
+
+    /**
+     * Custom constructor
+     *
+     * @return void
+     */
+    protected function _init()
+    {
+        $this->_blocks['groupedViewBlock'] = [
+            'name' => 'groupedViewBlock',
+            'class' => 'Magento\GroupedProduct\Test\Block\Catalog\Product\View',
+            'locator' => '.product-info-main',
+            'strategy' => 'css selector',
+        ];
+        parent::_init();
+    }
+
+    /**
+     * @return \Magento\GroupedProduct\Test\Block\Catalog\Product\View
+     */
+    public function getGroupedViewBlock()
+    {
+        return $this->getBlockInstance('groupedViewBlock');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Page/Product/CatalogProductView.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Page/Product/CatalogProductView.xml
new file mode 100755
index 0000000000000000000000000000000000000000..925691cd6a4a4cffa1f500bad84a850067488879
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Page/Product/CatalogProductView.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<page mca="catalog/product/view">
+    <block>
+        <name>groupedViewBlock</name>
+        <class>Magento\GroupedProduct\Test\Block\Catalog\Product\View</class>
+        <locator>.product-info-main</locator>
+        <strategy>css selector</strategy>
+    </block>
+</page>
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/CatalogProductGrouped.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/CatalogProductGrouped.php
index d97cbf8e1ce1aecbbc0af30ad2eeae4cd2944f99..de41d75a51d5c2871673dc5b4a6dfebcc8baa32c 100644
--- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/CatalogProductGrouped.php
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/CatalogProductGrouped.php
@@ -45,7 +45,25 @@ class CatalogProductGrouped extends AbstractRepository
         $this->_data['default'] = [
             'name' => 'Test grouped product %isolation%',
             'sku' => 'sku_test_grouped_product_%isolation%',
-            'price' => ['value' => 120.00],
+            'weight' => 30.0000,
+            'category_ids' => ['presets' => 'default'],
+            'associated' => ['preset' => 'defaultSimpleProduct'],
+            'status' => 'Product online',
+            'visibility' => 'Catalog, Search',
+            'tax_class_id' => ['dataSet' => 'Taxable Goods'],
+            'url_key' => 'test-grouped-product-%isolation%',
+            'quantity_and_stock_status' => [
+                'qty' => 666.0000,
+                'is_in_stock' => 'In Stock',
+            ],
+            'website_ids' => ['Main Website'],
+            'attribute_set_id' => ['dataSet' => 'default'],
+        ];
+
+        $this->_data['grouped_product_with_price'] = [
+            'name' => 'Test grouped product %isolation%',
+            'sku' => 'sku_test_grouped_product_%isolation%',
+            'price' => ['value' => '-', 'preset' => 'starting-560'],
             'weight' => 30.0000,
             'category_ids' => ['presets' => 'default'],
             'associated' => ['preset' => 'defaultSimpleProduct'],
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/CreateGroupedProductEntityTest.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/CreateGroupedProductEntityTest.php
new file mode 100755
index 0000000000000000000000000000000000000000..ed912e0c5b66412745e274be662d6fa69ffb8591
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/CreateGroupedProductEntityTest.php
@@ -0,0 +1,112 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GroupedProduct\Test\TestCase;
+
+use Mtf\TestCase\Injectable;
+use Magento\Catalog\Test\Fixture\CatalogCategory;
+use Magento\GroupedProduct\Test\Fixture\CatalogProductGrouped;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew;
+
+/**
+ * Test Creation for CreateGroupedProductEntity
+ *
+ * Preconditions:
+ * 1. Simple product is created.
+ * 2. Virtual product is created.
+ *
+ * Test Flow:
+ * 1. Login to the backend.
+ * 2. Navigate to Products > Catalog.
+ * 3. Start to create Grouped Product.
+ * 4. Fill in data according to data set.
+ * 5. Click "Add Products to Group" button and select products'.
+ * 6. Click "Add Selected Product" button
+ * 7. Save the Product.
+ * 8. Perform assertions.
+ *
+ * @group Grouped_Product_(MX)
+ * @ZephyrId MAGETWO-24877
+ */
+class CreateGroupedProductEntityTest extends Injectable
+{
+    /**
+     * Page product on backend
+     *
+     * @var CatalogProductIndex
+     */
+    protected $catalogProductIndex;
+
+    /**
+     * New page on backend
+     *
+     * @var CatalogProductNew
+     */
+    protected $catalogProductNew;
+
+    /**
+     * Persist category
+     *
+     * @param CatalogCategory $category
+     * @return array
+     */
+    public function __prepare(CatalogCategory $category)
+    {
+        $category->persist();
+        return ['category' => $category];
+    }
+
+    /**
+     * Injection pages
+     *
+     * @param CatalogProductIndex $catalogProductIndexNewPage
+     * @param CatalogProductNew $catalogProductNewPage
+     * @return void
+     */
+    public function __inject(
+        CatalogProductIndex $catalogProductIndexNewPage,
+        CatalogProductNew $catalogProductNewPage
+    ) {
+        $this->catalogProductIndex = $catalogProductIndexNewPage;
+        $this->catalogProductNew = $catalogProductNewPage;
+    }
+
+    /**
+     * Test create grouped product
+     *
+     * @param CatalogProductGrouped $product
+     * @param CatalogCategory $category
+     * @return void
+     */
+    public function test(CatalogProductGrouped $product, CatalogCategory $category)
+    {
+        //Steps
+        $this->catalogProductIndex->open();
+        $this->catalogProductIndex->getGridPageActionBlock()->addProduct('grouped');
+        $productBlockForm = $this->catalogProductNew->getForm();
+        $productBlockForm->fill($product, null, $category);
+        $this->catalogProductNew->getFormAction()->save();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/CreateGroupedProductEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/CreateGroupedProductEntityTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..6c8d715e10f0f2797f3007f5bb05f639657f78ad
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/CreateGroupedProductEntityTest/test.csv
@@ -0,0 +1,9 @@
+"product/data/name";"product/data/sku";"product/data/quantity_and_stock_status/is_in_stock";"product/data/category";"product/data/description";"product/data/associated/products";"product/data/associated/preset";"product/data/short_description";"isRequired";"constraint"
+"GroupedProduct %isolation%";"GroupedProduct_sku%isolation%";"In Stock";"category_%isolation%";"This is description for grouped product";"catalogProductSimple::simple_for_composite_products,catalogProductSimple::simple_for_composite_products";"defaultSimpleProduct";"This is short description for grouped product";"Yes";"assertProductSaveMessage, assertGroupedProductsDefaultQty"
+"GroupedProduct %isolation%";"-";"In Stock";"-";"-";"catalogProductSimple::simple_for_composite_products,catalogProductSimple::simple_for_composite_products";"defaultSimpleProduct";"-";"No";"assertProductInStock, assertProductSkuAutoGenerated, assertProductSearchableBySku"
+"GroupedProduct %isolation%";"GroupedProduct_sku%isolation%";"Out of Stock";"category_%isolation%";"-";"catalogProductSimple::simple_for_composite_products,catalogProductSimple::simple_for_composite_products";"defaultSimpleProduct";"-";"No";"assertProductOutOfStock"
+"GroupedProduct %isolation%";"GroupedProduct_sku%isolation%";"In Stock";"category_%isolation%";"-";"catalogProductSimple::simple_for_composite_products,catalogProductSimple::simple_for_composite_products";"defaultSimpleProduct";"-";"No";"assertGroupedProductsDefaultQty, assertGroupedProductForm, assertProductPage"
+"GroupedProduct %isolation%";"GroupedProduct_sku%isolation%";"In Stock";"category_%isolation%";"-";"catalogProductSimple::withSpecialPrice,catalogProductSimple::withSpecialPrice";"defaultSimpleProduct";"-";"No";"assertSpecialPriceOnGroupedProductPage, assertGroupedProductForm, assertProductPage"
+"GroupedProduct %isolation%";"GroupedProduct_sku%isolation%";"In Stock";"category_%isolation%";"-";"catalogProductSimple::simple_with_group_price,catalogProductSimple::simple_with_group_price";"defaultSimpleProduct";"-";"No";"assertGroupedPriceOnGroupedProductPage, assertGroupedProductForm, assertProductPage"
+"GroupedProduct %isolation%";"GroupedProduct_sku%isolation%";"In Stock";"category_%isolation%";"-";"catalogProductVirtual::virtual_product,catalogProductVirtual::virtual_product";"defaultVirtualProduct";"-";"Yes";"assertProductSaveMessage, assertGroupedProductsDefaultQty"
+"GroupedProduct %isolation%";"GroupedProduct_sku%isolation%";"In Stock";"category_%isolation%";"-";"catalogProductSimple::simple_with_tier_price,catalogProductSimple::simple_with_tier_price";"defaultSimpleProduct";"-";"No";"assertTierPriceOnGroupedProductPage, assertGroupedProductForm, assertProductPage"
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/etc/global/constraint.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/etc/global/constraint.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ee4fcf2cb0c6caacb2d5b491d332bf882a6bd683
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/etc/global/constraint.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<constraint>
+    <assertGroupedProductsDefaultQty module="Magento_GroupedProduct">
+        <severeness>low</severeness>
+    </assertGroupedProductsDefaultQty>
+    <assertGroupedProductForm module="Magento_GroupedProduct">
+        <severeness>low</severeness>
+    </assertGroupedProductForm>
+    <assertTierPriceOnGroupedProductPage module="Magento_GroupedProduct">
+        <severeness>low</severeness>
+    </assertTierPriceOnGroupedProductPage>
+    <assertSpecialPriceOnGroupedProductPage module="Magento_GroupedProduct">
+        <severeness>low</severeness>
+    </assertSpecialPriceOnGroupedProductPage>
+    <assertGroupedPriceOnGroupedProductPage module="Magento_GroupedProduct">
+        <severeness>low</severeness>
+    </assertGroupedPriceOnGroupedProductPage>
+</constraint>
diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/etc/global/fixture.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/etc/global/fixture.xml
index 6e618562b008cc4c888516acca1a2637d2d5e672..8c5d35ae0c9f71f74bfe4d9ae3f61870086b43b5 100644
--- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/etc/global/fixture.xml
+++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/etc/global/fixture.xml
@@ -28,20 +28,13 @@
         <type>eav</type>
         <entity_type>catalog_product</entity_type>
         <product_type>grouped</product_type>
-        <collection>Magento\GroupedProduct\Model\Resource\Product\Collection</collection>
+        <collection>Magento\GroupedProduct\Model\Resource\Product\Type\Grouped\AssociatedProductsCollection</collection>
         <identifier>sku</identifier>
         <fields>
             <id>
                 <attribute_code>id</attribute_code>
                 <backend_type>virtual</backend_type>
             </id>
-            <grouped_products>
-                <attribute_code>grouped_selections</attribute_code>
-                <backend_type>virtual</backend_type>
-                <is_required>1</is_required>
-                <group>grouped</group>
-                <fixture>Magento\GroupedProduct\Test\Fixture\Grouped\Selections</fixture>
-            </grouped_products>
         </fields>
         <data_set>
             <sku />
diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Block/Product/View.php b/dev/tests/functional/tests/app/Magento/Review/Test/Block/Product/View.php
index 57e24509a585ebfa9fd39a07afa8df9e13012670..768536202e63b6cea4f6afe9834b060e77a0d90c 100755
--- a/dev/tests/functional/tests/app/Magento/Review/Test/Block/Product/View.php
+++ b/dev/tests/functional/tests/app/Magento/Review/Test/Block/Product/View.php
@@ -39,28 +39,28 @@ class View extends Block
      *
      * @var string
      */
-    protected $itemSelector = '.reviews.items .item.review';
+    protected $itemSelector = '.review-items .review-item';
 
     /**
      * Nickname selector
      *
      * @var string
      */
-    protected $nicknameSelector = '.nickname';
+    protected $nicknameSelector = '.review-author .review-details-value';
 
     /**
      * Title selector
      *
      * @var string
      */
-    protected $titleSelector = '.title';
+    protected $titleSelector = '.review-title';
 
     /**
      * Detail selector
      *
      * @var string
      */
-    protected $detailSelector = '.content';
+    protected $detailSelector = '.review-content';
 
     /**
      * Selectors mapping
diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingOnReviewPage.php b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingOnReviewPage.php
index aec069bf2e271ba2c2e7e682a29b71d5333d1a94..6211b78e4ba0fb7d44214a0db69a5e7c24bc37fb 100755
--- a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingOnReviewPage.php
+++ b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingOnReviewPage.php
@@ -65,9 +65,9 @@ class AssertProductRatingOnReviewPage extends AbstractAssertForm
             ($reviewInitial && $reviewInitial->hasData('ratings')) ? $reviewInitial->getRatings() : [],
             $review->hasData('ratings') ? $review->getRatings() : []
         );
-        $ratingReview = $this->sortData($ratingReview, ['::title']);
+        $ratingReview = $this->sortDataByPath($ratingReview, '::title');
         $ratingForm = $reviewEdit->getReviewForm()->getRatings();
-        $ratingForm = $this->sortData($ratingForm, ['::title']);
+        $ratingForm = $this->sortDataByPath($ratingForm, '::title');
         $error = $this->verifyData($ratingReview, $ratingForm);
         \PHPUnit_Framework_Assert::assertTrue(empty($error), $error);
     }
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Block/Switcher.php b/dev/tests/functional/tests/app/Magento/Store/Test/Block/Switcher.php
index 4b72b0a321ca5c14f26104abe0e3d1cf20a5b6bd..8e891f8a7b4aed1dfb79d7a12783277a0e21929c 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Block/Switcher.php
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Block/Switcher.php
@@ -44,7 +44,19 @@ class Switcher extends Block
      */
     public function selectStoreView($name)
     {
-        $this->_rootElement->find($this->dropDownButton)->click();
-        $this->_rootElement->find($name, Locator::SELECTOR_LINK_TEXT)->click();
+        if ($this->_rootElement->find($this->dropDownButton)->isVisible() && ($this->getStoreView() !== $name)) {
+            $this->_rootElement->find($this->dropDownButton)->click();
+            $this->_rootElement->find($name, Locator::SELECTOR_LINK_TEXT)->click();
+        }
+    }
+
+    /**
+     * Get store view
+     *
+     * @return string
+     */
+    public function getStoreView()
+    {
+        return $this->_rootElement->find($this->dropDownButton)->getText();
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Store.php b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Store.php
index 6b2549d2845803b9a6d31e3de7639490f12558a9..e530f73b84fc166bc5ddc7d198591dd63275f190 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Store.php
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Store.php
@@ -1,7 +1,5 @@
 <?php
 /**
- * Store fixture
- *
  * Magento
  *
  * NOTICE OF LICENSE
@@ -26,67 +24,119 @@
 
 namespace Magento\Store\Test\Fixture;
 
-use Mtf\Fixture\DataFixture;
-use Mtf\Factory\Factory;
+use Mtf\Fixture\InjectableFixture;
 
-class Store extends DataFixture
+/**
+ * Class Store
+ * Store View fixture
+ */
+class Store extends InjectableFixture
 {
     /**
-     * @param \Mtf\System\Config $configuration
-     * @param array $placeholders
+     * @var string
      */
-    public function __construct(\Mtf\System\Config $configuration, array $placeholders = array())
-    {
-        parent::__construct($configuration, $placeholders);
-        $this->_placeholders = $placeholders;
-    }
+    protected $repositoryClass = 'Magento\Store\Test\Repository\Store';
 
     /**
-     * Initialize fixture data
+     * @var string
      */
-    protected function _initData()
+    protected $handlerInterface = 'Magento\Store\Test\Handler\Store\StoreInterface';
+
+    protected $defaultDataSet = [
+        'group_id' => 'Main Website Store',
+        'name' => 'Custom_Store_%isolation%',
+        'code' => 'code_%isolation%',
+        'is_active' => 'Enabled',
+    ];
+
+    protected $store_id = [
+        'attribute_code' => 'store_id',
+        'backend_type' => 'smallint',
+        'is_required' => '1',
+        'default_value' => '',
+        'input' => '',
+    ];
+
+    protected $code = [
+        'attribute_code' => 'code',
+        'backend_type' => 'varchar',
+        'is_required' => '',
+        'default_value' => '',
+        'input' => 'text',
+    ];
+
+    protected $website_id = [
+        'attribute_code' => 'website_id',
+        'backend_type' => 'smallint',
+        'is_required' => '',
+        'default_value' => '0',
+        'input' => '',
+    ];
+
+    protected $group_id = [
+        'attribute_code' => 'group_id',
+        'backend_type' => 'smallint',
+        'is_required' => '',
+        'default_value' => '0',
+        'input' => 'select',
+    ];
+
+    protected $name = [
+        'attribute_code' => 'name',
+        'backend_type' => 'varchar',
+        'is_required' => '',
+        'default_value' => '',
+        'input' => 'text',
+    ];
+
+    protected $sort_order = [
+        'attribute_code' => 'sort_order',
+        'backend_type' => 'smallint',
+        'is_required' => '',
+        'default_value' => '0',
+        'input' => 'text',
+    ];
+
+    protected $is_active = [
+        'attribute_code' => 'is_active',
+        'backend_type' => 'smallint',
+        'is_required' => '',
+        'default_value' => '0',
+        'input' => 'select',
+    ];
+
+    public function getStoreId()
     {
-        $this->_data = array(
-            'fields' => array(
-                'group' => array(
-                    'value' => 'Main Website Store',
-                    'input' => 'select'
-                ),
-                'name' => array(
-                    'value' => 'DE%isolation%'
-                ),
-                'code' => array(
-                    'value' => 'de%isolation%'
-                ),
-                'is_active' => array(
-                    'value' => 'Enabled',
-                    'input' => 'select',
-                ),
-            )
-        );
-
-        $this->_repository = Factory::getRepositoryFactory()
-            ->getMagentoStoreCustomStore($this->_dataConfig, $this->_data);
+        return $this->getData('store_id');
     }
 
+    public function getCode()
+    {
+        return $this->getData('code');
+    }
 
-    /**
-     * Create Store
-     *
-     * @return Store
-     */
-    public function persist()
+    public function getWebsiteId()
     {
-        return Factory::getApp()->magentoStoreCreateStore($this);
+        return $this->getData('website_id');
+    }
+
+    public function getGroupId()
+    {
+        return $this->getData('group_id');
     }
 
-    /**
-     * Get name
-     *
-     * @return string
-     */
     public function getName()
     {
-        return $this->getData('fields/name/value');
+        return $this->getData('name');
+    }
+
+    public function getSortOrder()
+    {
+        return $this->getData('sort_order');
+    }
+
+    public function getIsActive()
+    {
+        return $this->getData('is_active');
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Store.xml b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Store.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cd4f421f55cc2210d0749c073104562003680470
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Fixture/Store.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<fixture class="Magento\Store\Test\Fixture\Store">
+    <module>Magento_Store</module>
+    <type>flat</type>
+    <entity_type>store</entity_type>
+    <collection>Magento\Store\Model\Resource\Store\Collection</collection>
+    <fields>
+        <store_id>
+            <attribute_code>store_id</attribute_code>
+            <backend_type>smallint</backend_type>
+            <is_required>1</is_required>
+            <default_value></default_value>
+            <input></input>
+        </store_id>
+        <code>
+            <attribute_code>code</attribute_code>
+            <backend_type>varchar</backend_type>
+            <is_required></is_required>
+            <default_value></default_value>
+            <input>text</input>
+        </code>
+        <website_id>
+            <attribute_code>website_id</attribute_code>
+            <backend_type>smallint</backend_type>
+            <is_required></is_required>
+            <default_value>0</default_value>
+            <input></input>
+        </website_id>
+        <group_id>
+            <attribute_code>group_id</attribute_code>
+            <backend_type>smallint</backend_type>
+            <is_required></is_required>
+            <default_value>0</default_value>
+            <input>select</input>
+        </group_id>
+        <name>
+            <attribute_code>name</attribute_code>
+            <backend_type>varchar</backend_type>
+            <is_required></is_required>
+            <default_value></default_value>
+            <input>text</input>
+        </name>
+        <sort_order>
+            <attribute_code>sort_order</attribute_code>
+            <backend_type>smallint</backend_type>
+            <is_required></is_required>
+            <default_value>0</default_value>
+            <input>text</input>
+        </sort_order>
+        <is_active>
+            <attribute_code>is_active</attribute_code>
+            <backend_type>smallint</backend_type>
+            <is_required></is_required>
+            <default_value>0</default_value>
+            <input>select</input>
+        </is_active>
+    </fields>
+    <data_set></data_set>
+    <data_config></data_config>
+    <repository_class>Magento\Store\Test\Repository\Store</repository_class>
+    <handler_interface>Magento\Store\Test\Handler\Store\StoreInterface</handler_interface>
+</fixture>
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Curl/CreateStore.php b/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Curl/CreateStore.php
deleted file mode 100644
index 222d27febaef89caf6e5524e8892589507f4de86..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Curl/CreateStore.php
+++ /dev/null
@@ -1,116 +0,0 @@
-<?php
-/**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @spi
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
- */
-
-namespace Magento\Store\Test\Handler\Curl;
-
-use Mtf\Fixture\FixtureInterface;
-use Mtf\Handler\Curl;
-use Mtf\Util\Protocol\CurlInterface;
-use Mtf\Util\Protocol\CurlTransport;
-use Mtf\Util\Protocol\CurlTransport\BackendDecorator;
-use Mtf\System\Config;
-
-/**
- * Curl handler for persisting Magento store view
- *
- */
-class CreateStore extends Curl
-{
-    /**
-     * Prepare POST data for creating store view request
-     *
-     * @param array $params
-     * @return array
-     */
-    protected function _prepareData($params)
-    {
-        $data = array();
-        foreach ($params['fields'] as $name => $config) {
-            $data[$name] = $config['value'];
-        }
-        return $data;
-    }
-
-    /**
-     * Get store id by store name
-     *
-     * @param string $storeName
-     * @return int
-     * @throws \UnexpectedValueException
-     */
-    protected function _getStoreIdByStoreName($storeName)
-    {
-        //Set pager limit to 2000 in order to find created store view by name
-        $url = $_ENV['app_backend_url'] . 'admin/system_store/index/sort/store_title/dir/asc/limit/2000';
-        $curl = new BackendDecorator(new CurlTransport(), new Config);
-        $curl->addOption(CURLOPT_HEADER, 1);
-        $curl->write(CurlInterface::POST, $url, '1.0');
-        $response = $curl->read();
-
-        $expectedUrl = '/admin/system_store/editStore/store_id/';
-        $expectedUrl = preg_quote($expectedUrl);
-        $expectedUrl = str_replace('/', '\/', $expectedUrl);
-        preg_match('/' . $expectedUrl . '([0-9]*)\/(.)*>' . $storeName . '<\/a>/', $response, $matches);
-
-        if (empty($matches)) {
-            throw new \UnexpectedValueException('Cannot find store id');
-        }
-
-        return intval($matches[1]);
-    }
-
-    /**
-     * Post request for persisting Magento Store View
-     *
-     * @param FixtureInterface $fixture
-     * @return array
-     * @throws \UnexpectedValueException
-     * @throws \UnderflowException
-     */
-    public function persist(FixtureInterface $fixture = null)
-    {
-        $data = $this->_prepareData($fixture->getData());
-        $data['store_id'] = '';
-        $fields = array(
-            'store' => $data,
-            'store_action' => 'add',
-            'store_type' => 'store',
-        );
-
-        $url = $_ENV['app_backend_url'] . 'admin/system_store/save/';
-        $curl = new BackendDecorator(new CurlTransport(), new Config());
-        $curl->write(CurlInterface::POST, $url, '1.0', array(), $fields);
-        $response = $curl->read();
-        $curl->close();
-
-        if (!preg_match('/The store view has been saved/', $response)) {
-            throw new \UnderflowException('Store was\'t saved');
-        }
-
-        $data['id'] = $this->_getStoreIdByStoreName($fixture->getData('fields/name/value'));
-
-        return $data;
-    }
-}
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Store/Curl.php b/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Store/Curl.php
new file mode 100644
index 0000000000000000000000000000000000000000..e7c2046822b2fc45ca09be3ea4ab74a868a96a5b
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Store/Curl.php
@@ -0,0 +1,143 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Store\Test\Handler\Store;
+
+use Mtf\System\Config;
+use Mtf\Fixture\FixtureInterface;
+use Mtf\Util\Protocol\CurlInterface;
+use Mtf\Util\Protocol\CurlTransport;
+use Mtf\Util\Protocol\CurlTransport\BackendDecorator;
+use Mtf\Handler\Curl as AbstractCurl;
+
+/**
+ * Class Curl
+ * Curl handler for creating Store view.
+ */
+class Curl extends AbstractCurl implements StoreInterface
+{
+    /**
+     * Url for saving data
+     *
+     * @var string
+     */
+    protected $saveUrl = 'admin/system_store/save';
+
+    /**
+     * Mapping values for data
+     *
+     * @var array
+     */
+    protected $mappingData = [
+        'group_id' => [
+            'Main Website Store' => 1
+        ],
+        'is_active' => [
+            'Enabled' => 1,
+            'Disabled' => 0
+        ],
+    ];
+
+    /**
+     * POST request for creating store
+     *
+     * @param FixtureInterface|null $fixture [optional]
+     * @return array
+     * @throws \Exception
+     */
+    public function persist(FixtureInterface $fixture = null)
+    {
+        $data = $this->prepareData($fixture);
+        $url = $_ENV['app_backend_url'] . $this->saveUrl;
+        $curl = new BackendDecorator(new CurlTransport(), new Config());
+        $curl->write(CurlInterface::POST, $url, '1.0', array(), $data);
+        $response = $curl->read();
+        $curl->close();
+        if (!strpos($response, 'data-ui-id="messages-message-success"')) {
+            throw new \Exception("Store View entity creating  by curl handler was not successful! Response: $response");
+        }
+
+        return ['store_id' => $this->getStoreId($fixture->getName())];
+    }
+
+    /**
+     * Prepare data from text to values
+     *
+     * @param $fixture
+     * @return array
+     */
+    protected function prepareData($fixture)
+    {
+        $data['store'] = $this->replaceMappingData($fixture->getData());
+        $data['store_action'] = isset($data['store_action']) ? $data['store_action'] : 'add';
+        $data['store_type'] = isset($data['store_type']) ? $data['store_type'] : 'store';
+
+        return $data;
+    }
+
+    /**
+     * Get Store id by name after creating Store
+     *
+     * @param string $name
+     * @return int|null
+     * @throws \Exception
+     */
+    protected function getStoreId($name)
+    {
+        //Set pager limit to 2000 in order to find created store view by name
+        $url = $_ENV['app_backend_url'] . 'admin/system_store/index/sort/store_title/dir/asc/limit/2000';
+        $curl = new BackendDecorator(new CurlTransport(), new Config);
+        $curl->addOption(CURLOPT_HEADER, 1);
+        $curl->write(CurlInterface::POST, $url, '1.0');
+        $response = $curl->read();
+
+        $expectedUrl = '/admin/system_store/editStore/store_id/';
+        $expectedUrl = preg_quote($expectedUrl);
+        $expectedUrl = str_replace('/', '\/', $expectedUrl);
+        preg_match('/' . $expectedUrl . '([0-9]*)\/(.)*>' . $name . '<\/a>/', $response, $matches);
+
+        if (empty($matches)) {
+            throw new \Exception('Cannot find store id');
+        }
+
+        return empty($matches[1]) ? null : $matches[1];
+    }
+
+    /**
+     * Encoded filter parameters
+     *
+     * @param array $filter
+     * @return string
+     */
+    protected function encodeFilter(array $filter)
+    {
+        $result = [];
+        foreach ($filter as $name => $value) {
+            $result[] = "{$name}={$value}";
+        }
+        $result = implode('&', $result);
+
+        return base64_encode($result);
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Store/StoreInterface.php b/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Store/StoreInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..4430bda6e296737a024dfe78f62a19c341667d5f
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Handler/Store/StoreInterface.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Store\Test\Handler\Store;
+
+use Mtf\Handler\HandlerInterface;
+
+/**
+ * Interface StoreInterface
+ */
+interface StoreInterface extends HandlerInterface
+{
+    //
+}
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/CustomStore.php b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Store.php
similarity index 53%
rename from dev/tests/functional/tests/app/Magento/Store/Test/Repository/CustomStore.php
rename to dev/tests/functional/tests/app/Magento/Store/Test/Repository/Store.php
index 2911dbc2b3d1c7c8fa4f2f58f5e0bb865e51e29c..88d566f66e392f0d29c83c8c279ad2bf2420ea64 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/CustomStore.php
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Store.php
@@ -27,38 +27,38 @@ namespace Magento\Store\Test\Repository;
 use Mtf\Repository\AbstractRepository;
 
 /**
- * Class Custom Store Repository
- *
+ * Class Store
+ * Data for creation Catalog Price Rule
  */
-class CustomStore extends AbstractRepository
+class Store extends AbstractRepository
 {
     /**
-     * {@inheritdoc}
+     * @constructor
+     * @param array $defaultConfig
+     * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function __construct(array $defaultConfig = array(), array $defaultData = array())
+    public function __construct(array $defaultConfig = [], array $defaultData = [])
     {
-        $this->_data['default'] = array(
-            'config' => $defaultConfig,
-            'data' => $defaultData
-        );
+        $this->_data['default'] = [
+            'group_id' => 'Main Website Store',
+            'name' => 'Custom_Store_%isolation%',
+            'code' => 'code_%isolation%',
+            'is_active' => 'Enabled',
+            'store_id' => 1,
+        ];
+
+        $this->_data['All Store Views'] = [
+            'name' => 'All Store Views',
+            'store_id' => 0,
+        ];
 
-        $this->_data['custom_store']['data'] = array(
-            'fields' => array(
-                'group_id' => array(
-                    'value' => '%store_group%',
-                    'input' => 'select'
-                ),
-                'name' => array(
-                    'value' => 'StoreView%isolation%'
-                ),
-                'code' => array(
-                    'value' => 'storeview%isolation%'
-                ),
-                'is_active' => array(
-                    'value' => '1',
-                    'input' => 'select',
-                )
-            )
-        );
+        $this->_data['german'] = [
+            'group_id' => 'Main Website Store',
+            'name' => 'DE%isolation%',
+            'code' => 'de%isolation%',
+            'is_active' => 'Enabled',
+        ];
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/StoreTest.php b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/StoreTest.php
index 91a2df8e1c4e2e62356135a391249953bab5bdc4..a7826ac2da17eefc22285577fc4bd73a29b2b1f3 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/StoreTest.php
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/StoreTest.php
@@ -44,22 +44,23 @@ class StoreTest extends Functional
      */
     public function testCreateNewLocalizedStoreView()
     {
-        $storeFixture = Factory::getFixtureFactory()->getMagentoStoreStore();
+        $objectManager = Factory::getObjectManager();
+        $storeFixture = $objectManager->create('\Magento\Store\Test\Fixture\Store', ['dataSet' => 'german']);
 
         $storeListPage = Factory::getPageFactory()->getAdminSystemStore();
         $storeListPage->open();
-        $storeListPage->getPageActionsBlock()->addStoreView();
+        $storeListPage->getGridPageActions()->addStoreView();
 
         $newStorePage = Factory::getPageFactory()->getAdminSystemStoreNewStore();
-        $newStorePage->getFormBlock()->fill($storeFixture);
-        $newStorePage->getPageActionsBlock()->clickSave();
+        $newStorePage->getStoreForm()->fill($storeFixture);
+        $newStorePage->getFormPageActions()->save();
         $storeListPage->getMessagesBlock()->assertSuccessMessage();
         $this->assertContains(
             'The store view has been saved',
             $storeListPage->getMessagesBlock()->getSuccessMessages()
         );
         $this->assertTrue(
-            $storeListPage->getGridBlock()->isStoreExists($storeFixture->getName())
+            $storeListPage->getStoreGrid()->isStoreExists($storeFixture->getName())
         );
 
         $cachePage = Factory::getPageFactory()->getAdminCache();
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/etc/curl/di.xml b/dev/tests/functional/tests/app/Magento/Store/Test/etc/curl/di.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5299f3cbd8e82fd696cd1745eb5a16c651981a54
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/etc/curl/di.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+<preference for="Magento\Store\Test\Handler\Store\StoreInterface" type="\Magento\Store\Test\Handler\Store\Curl" />
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRate.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRate.php
index 79f847e4fbaa453d4794b671047d4585a1f75fa7..c6dca29436eaaa756bce1c41ac0cb6550450bbd8 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRate.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRate.php
@@ -82,6 +82,7 @@ class TaxRate extends AbstractRepository
             'rate' => '8.375',
             'tax_country_id' => 'United States',
             'tax_region_id' => 'New York',
+            'tax_postcode' => '*',
         ];
 
         $this->_data['us_ny_rate_8_1'] = [
@@ -89,6 +90,7 @@ class TaxRate extends AbstractRepository
             'rate' => '8.1',
             'tax_country_id' => 'United States',
             'tax_region_id' => 'New York',
+            'tax_postcode' => '*',
         ];
 
         $this->_data['paypal_rate_8_25'] = [
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRule.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRule.php
index 5e6b4807ce9b97c77f20faeeef2e7f0508572e5a..e006d07610ce1b34823183bcacfbaed6f6410957 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRule.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRule.php
@@ -47,6 +47,8 @@ class TaxRule extends AbstractRepository
                     1 => 'us_ny_rate_8_375',
                 ]
             ],
+            'priority' => '0',
+            'position' => '0',
         ];
 
         $this->_data['us_ca_ny_rule'] = [
@@ -80,6 +82,8 @@ class TaxRule extends AbstractRepository
                     0 => 'uk_full_tax_rate',
                 ],
             ],
+            'priority' => '0',
+            'position' => '0',
         ];
 
         $this->_data['tax_rule_default'] = [
diff --git a/dev/tests/functional/tests/app/Magento/Theme/Test/Block/Html/Footer.php b/dev/tests/functional/tests/app/Magento/Theme/Test/Block/Html/Footer.php
index b864569ac4c28b7227832eb1fc3f608d3b26773a..e8c6933006ce07de0866c7d41439a94005f4bb05 100644
--- a/dev/tests/functional/tests/app/Magento/Theme/Test/Block/Html/Footer.php
+++ b/dev/tests/functional/tests/app/Magento/Theme/Test/Block/Html/Footer.php
@@ -40,6 +40,13 @@ class Footer extends Block
      */
     protected $linkSelector = '//*[contains(@class, "links")]//a[contains(text(), "%s")]';
 
+    /**
+     * Variable selector
+     *
+     * @var string
+     */
+    protected $variableSelector = './/div[contains(@class, "links")]/*[text()="%s"]';
+
     /**
      * Click on link by name
      *
@@ -55,4 +62,18 @@ class Footer extends Block
         }
         $link->click();
     }
+
+    /**
+     * Check Variable visibility by html value
+     *
+     * @param string $htmlValue
+     * @return bool
+     */
+    public function checkVariable($htmlValue)
+    {
+        return $this->_rootElement->find(
+            sprintf($this->variableSelector, $htmlValue),
+            Locator::SELECTOR_XPATH
+        )->isVisible();
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Theme/Test/Block/Html/Title.php b/dev/tests/functional/tests/app/Magento/Theme/Test/Block/Html/Title.php
index b46afb86bb63dd185be049a3fdf45d0c264d3653..2f96684c3065e8cccb4503c1b1d2629789ae4c51 100644
--- a/dev/tests/functional/tests/app/Magento/Theme/Test/Block/Html/Title.php
+++ b/dev/tests/functional/tests/app/Magento/Theme/Test/Block/Html/Title.php
@@ -33,7 +33,7 @@ use Mtf\Block\Block;
 class Title extends Block
 {
     /**
-     * Get title of current category
+     * Get title of current page
      *
      * @return string
      */
diff --git a/dev/tests/functional/tests/app/Magento/Theme/Test/Block/Links.php b/dev/tests/functional/tests/app/Magento/Theme/Test/Block/Links.php
index 41120ea7989925890f581f148bcfb1c8ed162cca..5217cc42de342803687febfe69a7533920a9fa26 100644
--- a/dev/tests/functional/tests/app/Magento/Theme/Test/Block/Links.php
+++ b/dev/tests/functional/tests/app/Magento/Theme/Test/Block/Links.php
@@ -30,11 +30,25 @@ use Mtf\Client\Element;
 use Mtf\Client\Element\Locator;
 
 /**
+ * Class Links
  * Page Top Links block
- *
  */
 class Links extends Block
 {
+    /**
+     * Selector for qty products on compare
+     *
+     * @var string
+     */
+    protected $qtyCompareProducts = '.compare .counter.qty';
+
+    /**
+     * Link selector
+     *
+     * @var string
+     */
+    protected $link = '//a[contains(text(), "%s")]';
+
     /**
      * Open Link by title
      *
@@ -43,9 +57,10 @@ class Links extends Block
      */
     public function openLink($linkTitle)
     {
-        $this->_rootElement
-            ->find('//a[contains(text(), "' . $linkTitle . '")]', Locator::SELECTOR_XPATH)
-            ->click();
+        $link = $this->_rootElement->find(sprintf($this->link, $linkTitle), Locator::SELECTOR_XPATH);
+        if ($link->isVisible()) {
+            $link->click();
+        }
     }
 
     /**
@@ -56,8 +71,33 @@ class Links extends Block
      */
     public function isLinkVisible($linkTitle)
     {
-        return $this->_rootElement
-            ->find('//a[contains(text(), "' . $linkTitle . '")]', Locator::SELECTOR_XPATH)
-            ->isVisible();
+        return $this->_rootElement->find(sprintf($this->link, $linkTitle), Locator::SELECTOR_XPATH)->isVisible();
+    }
+
+    /**
+     * Get the number of products added to compare list
+     *
+     * @return string|bool
+     */
+    public function getQtyInCompareList()
+    {
+        $compareProductLink = $this->_rootElement->find($this->qtyCompareProducts);
+        if ($compareProductLink->isVisible()) {
+            preg_match_all('/^\d+/', $compareProductLink->getText(), $matches);
+            return $matches[0][0];
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Get url from link
+     *
+     * @param string $linkTitle
+     * @return string
+     */
+    public function getLinkUrl($linkTitle)
+    {
+        return trim($this->_rootElement->find(sprintf($this->link, $linkTitle), Locator::SELECTOR_XPATH)->getUrl());
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Edit/Form.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Edit/UrlRewriteForm.php
similarity index 76%
rename from dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Edit/Form.php
rename to dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Edit/UrlRewriteForm.php
index bbd0b6da9bd1cddb46959256625c3ce92321ea0c..cec8de81e554e8a96840e4f4a98d8968c9ae55ad 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Edit/Form.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Edit/UrlRewriteForm.php
@@ -26,31 +26,41 @@ namespace Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Edit;
 
 use Mtf\Client\Element;
 use Mtf\Fixture\FixtureInterface;
-use Magento\Backend\Test\Block\Widget\Form as FormWidget;
+use Magento\Backend\Test\Block\Widget\Form;
 
 /**
- * Class Form
+ * Class UrlRewriteForm
  * Catalog URL rewrite edit form
  */
-class Form extends FormWidget
+class UrlRewriteForm extends Form
 {
     /**
      * Fill the root form
      *
      * @param FixtureInterface $fixture
      * @param Element|null $element
+     * @param array $replace [optional]
      * @return $this
      */
-    public function fill(FixtureInterface $fixture, Element $element = null)
-    {
+    public function fill(
+        FixtureInterface $fixture,
+        Element $element = null,
+        array $replace = []
+    ) {
         $data = $fixture->getData();
-        $getData = $this->getData();
-        if (!$getData['target_path']) {
+        if (empty($this->getData()['target_path']) && !isset($data['target_path'])) {
             $entity = $fixture->getDataFieldConfig('id_path')['source']->getEntity();
             $data['target_path'] = $entity->hasData('identifier')
                 ? $entity->getIdentifier()
                 : $entity->getUrlKey() . '.html';
         }
+
+        foreach ($replace as $key => $pairs) {
+            if (isset($data[$key])) {
+                $data[$key] = str_replace(array_keys($pairs), $pairs, $data[$key]);
+            }
+        }
+
         // TODO: delete line after removing old fixture
         $fields = isset($data['fields']) ? $data['fields'] : $data;
         $mapping = $this->dataMapping($fields);
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Edit/Form.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Edit/UrlRewriteForm.xml
similarity index 100%
rename from dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Edit/Form.xml
rename to dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Edit/UrlRewriteForm.xml
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Selector.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Selector.php
index d55a83a9a4442ed025005cc3ba8c118f94e13417..c987eeef5a1dc8fe56448ede857d71868a0ceef3 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Selector.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Selector.php
@@ -38,6 +38,7 @@ class Selector extends Block
      * Select URL type
      *
      * @param string $urlrewriteType
+     * @return void
      */
     public function selectType($urlrewriteType)
     {
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertPageByUrlRewriteIsNotFound.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertPageByUrlRewriteIsNotFound.php
index bf78bda113e33918d0976f340166fc00d95cb139..1862fc3296473e0681675becff722ec0835a161f 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertPageByUrlRewriteIsNotFound.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertPageByUrlRewriteIsNotFound.php
@@ -51,8 +51,8 @@ class AssertPageByUrlRewriteIsNotFound extends AbstractConstraint
      * Checking the server response 404 page on frontend
      *
      * @param Browser $browser
-     * @param UrlRewrite $productRedirect
      * @param CatalogProductView $catalogProductView
+     * @param UrlRewrite $productRedirect
      * @return void
      */
     public function processAssert(
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteCmsPageRedirect.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteCustomSearchRedirect.php
similarity index 58%
rename from dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteCmsPageRedirect.php
rename to dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteCustomSearchRedirect.php
index 8a8988192c5009664d7ec988b3b9bd1281fd6bf1..2944bfa47c76854f8bfe9faa0436f0de93f7ef26 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteCmsPageRedirect.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteCustomSearchRedirect.php
@@ -27,13 +27,13 @@ namespace Magento\UrlRewrite\Test\Constraint;
 use Mtf\Client\Browser;
 use Mtf\Constraint\AbstractConstraint;
 use Magento\UrlRewrite\Test\Fixture\UrlRewrite;
-use Magento\Cms\Test\Fixture\CmsPage;
+use Magento\Catalog\Test\Page\Category\CatalogCategoryView;
 
 /**
- * Class AssertUrlRewriteCmsPageRedirect
- * Assert that created CMS Page URL Redirect lead to appropriate page in frontend
+ * Class AssertUrlRewriteCustomSearchRedirect
+ * Assert that product was found on search page
  */
-class AssertUrlRewriteCmsPageRedirect extends AbstractConstraint
+class AssertUrlRewriteCustomSearchRedirect extends AbstractConstraint
 {
     /**
      * Constraint severeness
@@ -43,46 +43,39 @@ class AssertUrlRewriteCmsPageRedirect extends AbstractConstraint
     protected $severeness = 'low';
 
     /**
-     * URL for CMS Page
-     *
-     * @var string
-     */
-    protected $url = 'cms/page/view/page_id/';
-
-    /**
-     * Assert that created CMS Page URL Redirect lead to appropriate page in frontend
+     * Assert that created entity was found on search page
      *
+     * @param UrlRewrite $initialRewrite
      * @param UrlRewrite $urlRewrite
-     * @param CmsPage $cmsPage
      * @param Browser $browser
+     * @param CatalogCategoryView $categoryView
      * @return void
      */
     public function processAssert(
+        UrlRewrite $initialRewrite,
         UrlRewrite $urlRewrite,
-        CmsPage $cmsPage,
-        Browser $browser
+        Browser $browser,
+        CatalogCategoryView $categoryView
     ) {
-        $browser->open($_ENV['app_frontend_url'] . $urlRewrite->getRequestPath());
-        $url = $urlRewrite->getOptions() == 'No'
+        $urlRequestPath = $urlRewrite->hasData('request_path')
             ? $urlRewrite->getRequestPath()
-            : $this->url . $cmsPage->getPageId();
+            : $initialRewrite->getRequestPath();
+        $browser->open($_ENV['app_frontend_url'] . $urlRequestPath);
+        $entity = $initialRewrite->getDataFieldConfig('id_path')['source']->getEntity()->getName();
 
-        \PHPUnit_Framework_Assert::assertEquals(
-            $browser->getUrl(),
-            $_ENV['app_frontend_url'] . $url,
-            'URL rewrite CMS Page redirect false.'
-            . "\nExpected: " . $_ENV['app_frontend_url'] . $url
-            . "\nActual: " . $browser->getUrl()
+        \PHPUnit_Framework_Assert::assertTrue(
+            $categoryView->getListProductBlock()->isProductVisible($entity),
+            "Created entity '{$entity}' isn't found."
         );
     }
 
     /**
-     * URL Redirect lead to appropriate page in frontend
+     * Returns a string representation of the object
      *
      * @return string
      */
     public function toString()
     {
-        return 'URL Redirect lead to appropriate page in frontend.';
+        return 'Product is found on search page.';
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteProductRedirect.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteProductRedirect.php
index 12a84e1d84023c013eae6723d732f8449bc5f5f7..1b0e0ab5543d56d5aaa5511975048d0ddb6cd23e 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteProductRedirect.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteProductRedirect.php
@@ -48,8 +48,8 @@ class AssertUrlRewriteProductRedirect extends AbstractConstraint
      *
      * @param UrlRewrite $urlRewrite
      * @param CatalogProductView $catalogProductView
-     * @param InjectableFixture $product
      * @param Browser $browser
+     * @param InjectableFixture $product
      * @return void
      */
     public function processAssert(
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteSuccessOutsideRedirect.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteSuccessOutsideRedirect.php
new file mode 100644
index 0000000000000000000000000000000000000000..38c657bfcb39a87c1ce172812527a527170460b5
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteSuccessOutsideRedirect.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\UrlRewrite\Test\Constraint;
+
+use Mtf\Client\Browser;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\UrlRewrite\Test\Fixture\UrlRewrite;
+
+/**
+ * Class AssertUrlRewriteSuccessOutsideRedirect
+ * Assert that outside redirect was success
+ */
+class AssertUrlRewriteSuccessOutsideRedirect extends AbstractConstraint
+{
+    /**
+     * Constraint severeness
+     *
+     * @var string
+     */
+    protected $severeness = 'low';
+
+    /**
+     * Assert that outside redirect was success
+     *
+     * @param UrlRewrite $urlRewrite
+     * @param Browser $browser
+     * @param UrlRewrite|null $initialRewrite [optional]
+     * @return void
+     */
+    public function processAssert(UrlRewrite $urlRewrite, Browser $browser, UrlRewrite $initialRewrite = null)
+    {
+        $urlRequestPath = $urlRewrite->hasData('request_path')
+            ? $urlRewrite->getRequestPath()
+            : $initialRewrite->getRequestPath();
+        $urlTargetPath = $urlRewrite->hasData('target_path')
+            ? $urlRewrite->getTargetPath()
+            : $initialRewrite->getTargetPath();
+
+        $browser->open($_ENV['app_frontend_url'] . $urlRequestPath);
+        $browserUrl = $browser->getUrl();
+
+        \PHPUnit_Framework_Assert::assertEquals(
+            $browserUrl,
+            $urlTargetPath,
+            'URL rewrite redirect false.'
+            . "\nExpected: " . $urlTargetPath
+            . "\nActual: " . $browserUrl
+        );
+    }
+
+    /**
+     * Returns a string representation of the object
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Custom outside URL rewrite redirect was success.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.php
index e8dd121aec0b7c7582ec973896aa6765cbaf21b0..1e6dbe108fedc55541ec5eea508682b8a25e480b 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.php
@@ -42,7 +42,7 @@ class UrlRewrite extends InjectableFixture
     protected $handlerInterface = 'Magento\UrlRewrite\Test\Handler\UrlRewrite\UrlRewriteInterface';
 
     protected $defaultDataSet = [
-        'store_id' => 'Default Store View',
+        'store_id' => 'Main Website/Main Website Store/Default Store View',
         'request_path' => 'test_request%isolation%',
     ];
 
@@ -62,6 +62,7 @@ class UrlRewrite extends InjectableFixture
         'backend_type' => 'varchar',
         'is_required' => '1',
         'default_value' => 'Default Store View',
+        'source' => 'Magento\UrlRewrite\Test\Fixture\UrlRewrite\StoreId',
         'input' => 'select',
     ];
 
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/IdPath.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/IdPath.php
index 20851760e2b312adb434a8ae2812feacefa035b5..9c0905a2456f30df5f765b4caca29bff7cd18d94 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/IdPath.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/IdPath.php
@@ -41,11 +41,11 @@ class IdPath implements FixtureInterface
     protected $data;
 
     /**
-     * Return category
+     * Return entity
      *
      * @var FixtureInterface
      */
-    protected $entity;
+    protected $entity = null;
 
     /**
      * Data set configuration settings
@@ -57,20 +57,20 @@ class IdPath implements FixtureInterface
     /**
      * @param FixtureFactory $fixtureFactory
      * @param array $params
-     * @param array $data
+     * @param array $data [optional]
      */
     public function __construct(FixtureFactory $fixtureFactory, array $params, array $data = [])
     {
         $this->params = $params;
-        if (!isset($data['entity'])) {
+        if (!isset($data['entity']) || $data['entity'] === '-') {
             $this->data = array_shift($data);
             return;
         }
         preg_match('`%(.*?)%`', $data['entity'], $dataSet);
-        $explodeValue = explode('::', $dataSet[1]);
-        if (!empty($explodeValue) && count($explodeValue) > 1) {
+        $entityConfig = isset($dataSet[1]) ? explode('::', $dataSet[1]) : [];
+        if (count($entityConfig) > 1) {
             /** @var FixtureInterface $fixture */
-            $this->entity = $fixtureFactory->createByCode($explodeValue[0], ['dataSet' => $explodeValue[1]]);
+            $this->entity = $fixtureFactory->createByCode($entityConfig[0], ['dataSet' => $entityConfig[1]]);
             $this->entity->persist();
             $id = $this->entity->hasData('id') ? $this->entity->getId() : $this->entity->getPageId();
             $this->data = preg_replace('`(%.*?%)`', $id, $data['entity']);
@@ -115,7 +115,7 @@ class IdPath implements FixtureInterface
     /**
      * Return entity
      *
-     * @return FixtureInterface
+     * @return FixtureInterface|null
      */
     public function getEntity()
     {
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/StoreId.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/StoreId.php
new file mode 100644
index 0000000000000000000000000000000000000000..aece5dd1fa3b655701480805f81bc8d8d5309f76
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/StoreId.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\UrlRewrite\Test\Fixture\UrlRewrite;
+
+use Mtf\Fixture\FixtureFactory;
+use Mtf\Fixture\FixtureInterface;
+use Magento\Store\Test\Fixture\Store;
+
+/**
+ * Class StoreId
+ * Store id source
+ */
+class StoreId implements FixtureInterface
+{
+    /**
+     * Resource data
+     *
+     * @var string
+     */
+    protected $data;
+
+    /**
+     * Data set configuration settings
+     *
+     * @var array
+     */
+    protected $params;
+
+    /**
+     * @param FixtureFactory $fixtureFactory
+     * @param array $params
+     * @param string $data
+     */
+    public function __construct(FixtureFactory $fixtureFactory, array $params, $data)
+    {
+        $this->params = $params;
+        if (preg_match('`%(.*?)%`', $data, $store)) {
+            /** @var Store $storeFixture */
+            $storeFixture = $fixtureFactory->createByCode('store', ['dataSet' => $store[1]]);
+            if (!$storeFixture->hasData('store_id')) {
+                $storeFixture->persist();
+            }
+            $data = str_replace('%' . $store[1] . '%', $storeFixture->getName(), $data);
+        }
+        $this->data = $data;
+    }
+
+    /**
+     * Persist custom selections products
+     *
+     * @return void
+     */
+    public function persist()
+    {
+        //
+    }
+
+    /**
+     * Return prepared data
+     *
+     * @param string|null $key [optional]
+     * @return string
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function getData($key = null)
+    {
+        return $this->data;
+    }
+
+    /**
+     * Return data set configuration settings
+     *
+     * @return array
+     */
+    public function getDataConfig()
+    {
+        return $this->params;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/Curl.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/Curl.php
index fdd1c3eab70782438e581ce3a618d238de8ec820..53b1b18ae578b92766e9452976341c92102609a5 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/Curl.php
@@ -46,7 +46,7 @@ class Curl extends AbstractCurl implements UrlRewriteInterface
         'store_id' => ['Default Store View' => 1],
         'options' => [
             'Temporary (302)' => 'R',
-            'Temporary (301)' => 'RP',
+            'Permanent (301)' => 'RP',
             'No' => ''
         ]
     ];
@@ -63,18 +63,18 @@ class Curl extends AbstractCurl implements UrlRewriteInterface
      *
      * @param FixtureInterface $fixture
      * @throws \Exception
-     * @return mixed|void
+     * @return void
      */
     public function persist(FixtureInterface $fixture = null)
     {
         $url = $_ENV['app_backend_url'] . $this->url . $fixture->getIdPath();
         $data = $this->replaceMappingData($fixture->getData());
         $curl = new BackendDecorator(new CurlTransport(), new Config());
-        $curl->write(CurlInterface::POST, $url, '1.0', array(), $data);
+        $curl->write(CurlInterface::POST, $url, '1.0', [], $data);
         $response = $curl->read();
 
         if (!strpos($response, 'data-ui-id="messages-message-success"')) {
-            throw new \Exception("Product creation by curl handler was not successful! Response: $response");
+            throw new \Exception("URL Rewrite creation by curl handler was not successful! Response: $response");
         }
         $curl->close();
     }
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.php
index 0ab76c1f45b56f4dc3f4e0b0b39f217d865077ce..a298098256c712e7149e8139c4809aff3bb8493b 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.php
@@ -42,7 +42,7 @@ class UrlrewriteEdit extends BackendPage
         ],
         'formBlock' => [
             'name' => 'formBlock',
-            'class' => 'Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Edit\Form',
+            'class' => 'Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Edit\UrlRewriteForm',
             'locator' => '#edit_form',
             'strategy' => 'css selector',
         ],
@@ -87,7 +87,7 @@ class UrlrewriteEdit extends BackendPage
     }
 
     /**
-     * @return \Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Edit\Form
+     * @return \Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Edit\UrlRewriteForm
      */
     public function getFormBlock()
     {
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.xml
index 35c41fe1518e9807ae1e38308e351b9b084d5b64..759ed44a996b56241d259d462e7708f2a7788eda 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.xml
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.xml
@@ -32,7 +32,7 @@
     </block>
     <block>
         <name>formBlock</name>
-        <class>Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Edit\Form</class>
+        <class>Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Edit\UrlRewriteForm</class>
         <locator>#edit_form</locator>
         <strategy>css selector</strategy>
     </block>
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewrite.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewrite.php
index e6cc865008aa4e8bf333aa6b57dafdf72ed10f7a..949d11d90aae6a254abc0223cabcd76a721cd6b8 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewrite.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewrite.php
@@ -42,8 +42,19 @@ class UrlRewrite extends AbstractRepository
     {
         $this->_data['default'] = [
             'request_path' => 'test-test-test%isolation%.html',
+            'target_path' => 'http://www.ebayinc.com/',
             'options' => 'Temporary (302)',
-            'store_id' => 'Default Store View'
+            'store_id' => 'Main Website/Main Website Store/Default Store View',
+            'id_path' =>  ["test%isolation%"]
+        ];
+
+        $this->_data['custom_rewrite_wishlist'] = [
+            'store_id' => 'Main Website/Main Website Store/Default Store View',
+            'request_path' => 'wishlist/%isolation%',
+            'target_path' => 'http://google.com',
+            'options' => 'Temporary (302)',
+            'description' => 'test description',
+            'id_path' => ['entity' => "wishlist/%catalogProductSimple::100_dollar_product%"]
         ];
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteCategory.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteCategory.php
index fa7d0c40ee35241df7b1b153c27e93b113d36be6..fbbac527e33ed07f381fa375a2dcb70f7f0572d5 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteCategory.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteCategory.php
@@ -41,22 +41,22 @@ class UrlRewriteCategory extends AbstractRepository
      */
     public function __construct(array $defaultConfig = array(), array $defaultData = array())
     {
-        $this->_data['default'] = array(
+        $this->_data['default'] = [
             'config' => $defaultConfig,
-            'data' => array(
-                'fields' => array(
-                    'request_path' => array(
+            'data' => [
+                'fields' => [
+                    'request_path' => [
                         'value' => '%rewritten_category_request_path%',
-                    ),
-                    'store' => array(
-                        'value' => 'Default Store View',
-                    ),
-                ),
-            ),
-        );
+                    ],
+                    'store_id' => [
+                        'value' => 'Main Website/Main Website Store/Default Store View',
+                    ],
+                ],
+            ],
+        ];
         $this->_data['category_with_permanent_redirect'] = $this->_data['default'];
-        $this->_data['category_with_permanent_redirect']['data']['fields']['options'] = array(
+        $this->_data['category_with_permanent_redirect']['data']['fields']['options'] = [
             'value' => 'Permanent (301)',
-        );
+        ];
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteProduct.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteProduct.php
index 355014c69b5f8acaa232243244c1aa7fb504b855..18d169447933399db793f41c5b63cc8f09917b6b 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteProduct.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteProduct.php
@@ -41,23 +41,23 @@ class UrlRewriteProduct extends AbstractRepository
      */
     public function __construct(array $defaultConfig = array(), array $defaultData = array())
     {
-        $this->_data['default'] = array(
+        $this->_data['default'] = [
             'config' => $defaultConfig,
-            'data' => array(
+            'data' => [
                 'url_rewrite_type' => 'For product',
-                'fields' => array(
-                    'request_path' => array(
+                'fields' => [
+                    'request_path' => [
                         'value' => '%rewritten_product_request_path%',
-                    ),
-                    'store' => array(
-                        'value' => 'Default Store View'
-                    ),
-                ),
-            ),
-        );
+                    ],
+                    'store_id' => [
+                        'value' => 'Main Website/Main Website Store/Default Store View'
+                    ],
+                ],
+            ],
+        ];
         $this->_data['product_with_temporary_redirect'] = $this->_data['default'];
-        $this->_data['product_with_temporary_redirect']['data']['fields']['options'] = array(
+        $this->_data['product_with_temporary_redirect']['data']['fields']['options'] = [
             'value' => 'Temporary (302)',
-        );
+        ];
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CategoryTest.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CategoryTest.php
index 84299120bd528abc0298dac74fa639fe3aa7053d..476fe956f19d342bbd7ee93b9459be2217679b7b 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CategoryTest.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CategoryTest.php
@@ -34,16 +34,12 @@ use Mtf\TestCase\Injectable;
  */
 class CategoryTest extends Injectable
 {
-    public function __inject()
-    {
-        //
-    }
-
     /**
      * Adding permanent redirect for category
      *
-     * @ZephyrId MAGETWO-12407
      * @param UrlRewriteCategory $urlRewriteCategory
+     * @return void
+     * @ZephyrId MAGETWO-12407
      */
     public function test(\Magento\UrlRewrite\Test\Fixture\UrlRewriteCategory $urlRewriteCategory)
     {
@@ -77,10 +73,10 @@ class CategoryTest extends Injectable
     /**
      * Assert that request URL redirects to target URL
      *
-     *
      * @param string $requestUrl
      * @param string $targetUrl
      * @param string $message
+     * @return void
      */
     protected function assertUrlRedirect($requestUrl, $targetUrl, $message = '')
     {
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCmsPageRewriteEntityTest/testCmsPageRewrite.csv b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCmsPageRewriteEntityTest/testCmsPageRewrite.csv
deleted file mode 100644
index 7edd14cc928acdc6f7f02af2592b12b233b0a3f8..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCmsPageRewriteEntityTest/testCmsPageRewrite.csv
+++ /dev/null
@@ -1,5 +0,0 @@
-"cmsPage/dataSet";"urlRewrite/data/store_id";"urlRewrite/data/request_path";"urlRewrite/data/options";"urlRewrite/data/description";"isRequired";"constraint"
-"default";"-";"request_path%isolation%";"No";"test_description_default";"Yes";"assertUrlRewriteSaveMessage, assertUrlRewriteCmsPageRedirect"
-"default";"-";"request_path%isolation%.html";"Temporary (302)";"test description_302";"Yes";"assertUrlRewriteSaveMessage, assertUrlRewriteCmsPageRedirect"
-"default";"-";"request_path%isolation%.htm";"Permanent (301)";"test description_301";"Yes";"assertUrlRewriteSaveMessage, assertUrlRewriteCmsPageRedirect"
-"default";"-";"request_path%isolation%.aspx";"Permanent (301)";"test description_%isolation%";"Yes";"assertUrlRewriteSaveMessage, assertUrlRewriteCmsPageRedirect"
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCustomUrlRewriteEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCustomUrlRewriteEntityTest/test.csv
index 7d2ee52bbb1c44f8363156e16f3f0a740521509c..b8daef7681ecdd67e673b0744d2fdb9cc913a8d0 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCustomUrlRewriteEntityTest/test.csv
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCustomUrlRewriteEntityTest/test.csv
@@ -1,5 +1,5 @@
-"urlRewrite/data/id_path/entity";"urlRewrite/data/request_path";"urlRewrite/data/options";"urlRewrite/data/description";"constraint"
-"category/%catalogCategory::default_subcategory%";"category_request_path%isolation%";"Permanent (301)";"test_description_relative path";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCustomRedirect"
-"product/%catalogProductSimple::default%";"product_request_path%isolation%";"Temporary (302)";"test_description_relative path";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCustomRedirect"
-"cms_page/%cmsPage::cms-page-test%";"cms_page_request_path%isolation%";"No";"test description_full path";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCustomRedirect"
-"cms_page/%cmsPage::cms-page-test%";"cms_page_request_path%isolation%";"Temporary (302)";"test description_full path";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCustomRedirect"
+"urlRewrite/data/store_id";"urlRewrite/data/id_path/entity";"urlRewrite/data/request_path";"urlRewrite/data/options";"urlRewrite/data/description";"constraint"
+"Main Website/Main Website Store/Default Store View";"category/%catalogCategory::default_subcategory%";"category_request_path%isolation%";"Permanent (301)";"test_description_relative path";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCustomRedirect"
+"Main Website/Main Website Store/Default Store View";"product/%catalogProductSimple::default%";"product_request_path%isolation%";"Temporary (302)";"test_description_relative path";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCustomRedirect"
+"Main Website/Main Website Store/Default Store View";"cms_page/%cmsPage::cms-page-test%";"cms_page_request_path%isolation%";"No";"test description_full path";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCustomRedirect"
+"Main Website/Main Website Store/Default Store View";"cms_page/%cmsPage::cms-page-test%";"cms_page_request_path%isolation%";"Temporary (302)";"test description_full path";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCustomRedirect"
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCustomUrlRewriteEntityTest.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCustomUrlRewriteEntityTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6a525d65302fefc340c83121f83ffdf2e6632288
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCustomUrlRewriteEntityTest.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\UrlRewrite\Test\TestCase;
+
+use Mtf\TestCase\Injectable;
+use Magento\UrlRewrite\Test\Fixture\UrlRewrite;
+use Magento\UrlRewrite\Test\Page\Adminhtml\UrlrewriteEdit;
+use Magento\UrlRewrite\Test\Page\Adminhtml\UrlrewriteIndex;
+
+/**
+ * Test Creation for DeleteCustomUrlRewriteEntity
+ *
+ * Test Flow:
+ * Preconditions:
+ * 1. Custom URL Rewrites is created.
+ *
+ * Steps:
+ * 1. Login to backend as Admin.
+ * 2. Go to the Marketing->SEO & Search->URL Redirects.
+ * 3. Search and open created URL Redirect.
+ * 4. Delete Redirect.
+ * 5. Perform all assertions.
+ *
+ * @group URL_Rewrites_(PS)
+ * @ZephyrId MAGETWO-26337
+ */
+class DeleteCustomUrlRewriteEntityTest extends Injectable
+{
+    /**
+     * Url rewrite index page
+     *
+     * @var UrlrewriteIndex
+     */
+    protected $urlRewriteIndex;
+
+    /**
+     * Url rewrite edit page
+     *
+     * @var UrlrewriteEdit
+     */
+    protected $urlRewriteEdit;
+
+    /**
+     * Inject pages
+     *
+     * @param UrlrewriteIndex $urlRewriteIndex
+     * @param UrlrewriteEdit $urlRewriteEdit
+     * @return void
+     */
+    public function __inject(UrlrewriteIndex $urlRewriteIndex, UrlrewriteEdit $urlRewriteEdit)
+    {
+        $this->urlRewriteIndex = $urlRewriteIndex;
+        $this->urlRewriteEdit = $urlRewriteEdit;
+    }
+
+    /**
+     * Delete custom URL Rewrite
+     *
+     * @param UrlRewrite $urlRewrite
+     * @return void
+     */
+    public function test(UrlRewrite $urlRewrite)
+    {
+        // Precondition
+        $urlRewrite->persist();
+
+        // Steps
+        $this->urlRewriteIndex->open();
+        $filter = ['request_path' => $urlRewrite->getRequestPath()];
+        $this->urlRewriteIndex->getUrlRedirectGrid()->searchAndOpen($filter);
+        $this->urlRewriteEdit->getPageMainActions()->delete();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCustomUrlRewriteEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCustomUrlRewriteEntityTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..3b512c81f0f1bff5354a9b204ee1d80cbe6e1d2e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCustomUrlRewriteEntityTest/test.csv
@@ -0,0 +1,2 @@
+"urlRewrite/dataSet";"constraint"
+"default";"assertUrlRewriteDeletedMessage, assertUrlRewriteNotInGrid, assertPageByUrlRewriteIsNotFound"
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/ProductTest.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/ProductTest.php
index 936f8235afe2a5931c306ad77c1e72d6e94c5b8f..805726b95a9087bc14b486d09767b591df557497 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/ProductTest.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/ProductTest.php
@@ -37,6 +37,7 @@ class ProductTest extends Functional
     /**
      * Adding temporary redirect for product
      *
+     * @return void
      * @ZephyrId MAGETWO-12409
      */
     public function testUrlRewriteCreation()
@@ -80,6 +81,7 @@ class ProductTest extends Functional
      * @param string $requestUrl
      * @param string $targetUrl
      * @param string $message
+     * @return void
      */
     protected function assertUrlRedirect($requestUrl, $targetUrl, $message = '')
     {
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest.php
index ae00d41bc8b458067df41f5abc3432dfabcae4aa..f432629855a858945d0d866fbadc646455a659b4 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest.php
@@ -104,7 +104,7 @@ class UpdateCategoryUrlRewriteEntityTest extends Injectable
      * @param UrlRewrite $urlRewrite
      * @return void
      */
-    public function testUpdateCategoryUrlRewrite(UrlRewrite $categoryRedirect, UrlRewrite $urlRewrite)
+    public function test(UrlRewrite $categoryRedirect, UrlRewrite $urlRewrite)
     {
         //Steps
         $this->urlRewriteIndex->open();
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..6f831e436460eb9de367a7fc7398e67d8ff34d22
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest/test.csv
@@ -0,0 +1,5 @@
+"urlRewrite/data/store_id";"category/dataSet";"categoryRewrite/dataSet";"urlRewrite/data/store_id";"urlRewrite/data/request_path";"urlRewrite/data/options";"urlRewrite/data/description";"constraint"
+"Main Website/Main Website Store/Default Store View";"default_subcategory";"default";"-";"test_request%isolation%";"No";"test_description_defalt";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCategoryRedirect"
+"Main Website/Main Website Store/Default Store View";"default_subcategory";"default";"-";"request_path%isolation%.html";"Temporary (302)";"test description_302";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCategoryRedirect"
+"Main Website/Main Website Store/Default Store View";"default_subcategory";"default";"-";"request_path%isolation%.htm";"Permanent (301)";"test description_301";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCategoryRedirect"
+"Main Website/Main Website Store/Default Store View";"default_subcategory";"default";"-";"request_path%isolation%.aspx";"Temporary (302)";"test description_%isolation%";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCategoryRedirect"
\ No newline at end of file
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest/testUpdateCategoryUrlRewrite.csv b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest/testUpdateCategoryUrlRewrite.csv
deleted file mode 100644
index 9b8902a40dcd563fed8f5b6db1305da58ea14249..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest/testUpdateCategoryUrlRewrite.csv
+++ /dev/null
@@ -1,5 +0,0 @@
-"category/dataSet";"categoryRewrite/dataSet";"urlRewrite/data/store_id";"urlRewrite/data/request_path";"urlRewrite/data/options";"urlRewrite/data/description";"constraint"
-"default_subcategory";"default";"-";"test_request%isolation%";"No";"test_description_defalt";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCategoryRedirect"
-"default_subcategory";"default";"-";"request_path%isolation%.html";"Temporary (302)";"test description_302";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCategoryRedirect"
-"default_subcategory";"default";"-";"request_path%isolation%.htm";"Permanent (301)";"test description_301";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCategoryRedirect"
-"default_subcategory";"default";"-";"request_path%isolation%.aspx";"Temporary (302)";"test description_%isolation%";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCategoryRedirect"
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCmsPageRewriteEntityTest.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCustomUrlRewriteEntityTest.php
similarity index 58%
rename from dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCmsPageRewriteEntityTest.php
rename to dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCustomUrlRewriteEntityTest.php
index 3bb8056bd214e3cd394514dfb83c03f51ba0edea..07a643add2cc258bf334bd0b98cf0af388e740f6 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCmsPageRewriteEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCustomUrlRewriteEntityTest.php
@@ -24,35 +24,32 @@
 
 namespace Magento\UrlRewrite\Test\TestCase;
 
-use Magento\UrlRewrite\Test\Page\Adminhtml\EditCmsPage;
 use Mtf\TestCase\Injectable;
-use Magento\Cms\Test\Fixture\CmsPage;
 use Magento\UrlRewrite\Test\Fixture\UrlRewrite;
 use Magento\UrlRewrite\Test\Page\Adminhtml\UrlrewriteEdit;
 use Magento\UrlRewrite\Test\Page\Adminhtml\UrlrewriteIndex;
 
 /**
- * Test Creation for CreateCmsPageRewriteEntity
+ * Test Creation for UpdateCustomUrlRewritesEntity
  *
  * Test Flow:
  *
- * Preconditions
- * 1. Create CMS-Page
+ * Preconditions:
+ * 1. Create default simple product
+ * 2. Create custom url rewrite
  *
- * Steps
+ * Steps:
  * 1. Login to backend as Admin
  * 2. Go to the Marketing-> SEO & Search->URL Redirects
- * 3. Click "Add Url Rewrite" button
- * 4. Select "For CMS Page" in Create URL Rewrite dropdown
- * 5. Select CMS page from preconditions in grid
- * 6. Fill data according to data set
- * 7. Save Rewrite
- * 8. Perform all assertions
+ * 3. Search and open created URL Redirect
+ * 4. Fill data according to data set
+ * 5. Save Redirect
+ * 6. Perform all assertions
  *
  * @group URL_Rewrites_(PS)
- * @ZephyrId MAGETWO-24847
+ * @ZephyrId MAGETWO-25784
  */
-class CreateCmsPageRewriteEntityTest extends Injectable
+class UpdateCustomUrlRewriteEntityTest extends Injectable
 {
     /**
      * Url rewrite index page
@@ -75,32 +72,48 @@ class CreateCmsPageRewriteEntityTest extends Injectable
      * @param UrlrewriteEdit $urlRewriteEdit
      * @return void
      */
-    public function __inject(
-        UrlrewriteIndex $urlRewriteIndex,
-        UrlrewriteEdit $urlRewriteEdit
-    ) {
+    public function __inject(UrlrewriteIndex $urlRewriteIndex, UrlrewriteEdit $urlRewriteEdit)
+    {
         $this->urlRewriteIndex = $urlRewriteIndex;
         $this->urlRewriteEdit = $urlRewriteEdit;
     }
 
     /**
-     * Create CMS page rewrites
+     * Update custom URL Rewrite
      *
-     * @param CmsPage $cmsPage
+     * @param UrlRewrite $initialRewrite
      * @param UrlRewrite $urlRewrite
      * @return void
      */
-    public function testCmsPageRewrite(CmsPage $cmsPage, UrlRewrite $urlRewrite)
+    public function test(UrlRewrite $initialRewrite, UrlRewrite $urlRewrite)
     {
-        //Preconditions
-        $cmsPage->persist();
+        //Precondition
+        $initialRewrite->persist();
+
         //Steps
         $this->urlRewriteIndex->open();
-        $this->urlRewriteIndex->getPageActionsBlock()->addNew();
-        $this->urlRewriteEdit->getUrlRewriteTypeSelectorBlock()->selectType('For CMS page');
-        $filter = ['title' => $cmsPage->getTitle()];
-        $this->urlRewriteEdit->getCmsGridBlock()->searchAndOpen($filter);
-        $this->urlRewriteEdit->getFormBlock()->fill($urlRewrite);
+        $filter = ['request_path' => $initialRewrite->getRequestPath()];
+        $replaceData = $this->getReplaceData($initialRewrite);
+        $this->urlRewriteIndex->getUrlRedirectGrid()->searchAndOpen($filter);
+        $this->urlRewriteEdit->getFormBlock()->fill($urlRewrite, null, $replaceData);
         $this->urlRewriteEdit->getPageMainActions()->save();
     }
+
+    /**
+     * Prepare data for replace
+     *
+     * @param UrlRewrite $initialRewrite
+     * @return array
+     */
+    protected function getReplaceData(UrlRewrite $initialRewrite)
+    {
+        $replaceData = [];
+        $entity = $initialRewrite->getDataFieldConfig('id_path')['source']->getEntity();
+
+        if ($entity) {
+            $replaceData['target_path'] = ['%name%' => $entity->getName()];
+        }
+
+        return $replaceData;
+    }
 }
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCustomUrlRewriteEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCustomUrlRewriteEntityTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..c614a683f0e573dc19e8c96cab66e899a7806fa9
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCustomUrlRewriteEntityTest/test.csv
@@ -0,0 +1,3 @@
+"initialRewrite/dataSet";"urlRewrite/data/store_id";"urlRewrite/data/request_path";"urlRewrite/data/target_path";"urlRewrite/data/options";"urlRewrite/data/description";"constraint"
+"default";"Main Website/Main Website Store/Default Store View";"wishlist/%isolation%";"http://www.magentocommerce.com/magento-connect/";"Permanent (301)";"test_description_relative path";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteSuccessOutsideRedirect"
+"custom_rewrite_wishlist";"Main Website/Main Website Store/Default Store View";"wishlist/%isolation%";"catalogsearch/result/?q=%name%";"Temporary (302)";"test_description_relative path";"assertUrlRewriteSaveMessage, assertUrlRewriteInGrid, assertUrlRewriteCustomSearchRedirect"
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/constraint.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/constraint.xml
index fd070420677a58039dd0d8a7fca10fb194804c92..e16f263cf173d87d838d2e4868f3b7913fb64bfc 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/constraint.xml
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/constraint.xml
@@ -67,15 +67,22 @@
             <browser class="Mtf\Client\Browser"/>
         </require>
     </assertPageByUrlRewriteIsNotFound>
-    <assertUrlRewriteCmsPageRedirect module="Magento_UrlRewrite">
+    <assertUrlRewriteCustomRedirect module="Magento_UrlRewrite">
+        <severeness>low</severeness>
+    </assertUrlRewriteCustomRedirect>
+    <assertUrlRewriteSuccessOutsideRedirect module="Magento_UrlRewrite">
         <severeness>low</severeness>
         <require>
-            <cmsPage class="Magento\Cms\Test\Fixture\CmsPage"/>
             <urlRewrite class="Magento\UrlRewrite\Test\Fixture\UrlRewrite"/>
             <browser class="Mtf\Client\Browser"/>
         </require>
-    </assertUrlRewriteCmsPageRedirect>
-    <assertUrlRewriteCustomRedirect module="Magento_UrlRewrite">
+    </assertUrlRewriteSuccessOutsideRedirect>
+    <assertUrlRewriteCustomSearchRedirect module="Magento_UrlRewrite">
         <severeness>low</severeness>
-    </assertUrlRewriteCustomRedirect>
+        <require>
+            <urlRewrite class="Magento\UrlRewrite\Test\Fixture\UrlRewrite"/>
+            <browser class="Mtf\Client\Browser"/>
+            <categoryView class="Magento\Catalog\Test\Page\Category\CatalogCategoryView"/>
+        </require>
+    </assertUrlRewriteCustomSearchRedirect>
 </constraint>
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/page.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/page.xml
index d8be3b72836dde3715635803f25982e39451ebde..0e1e33bb730f44a15a9209cbd00d91b71bf7999b 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/page.xml
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/page.xml
@@ -34,9 +34,4 @@
         <area>adminhtml</area>
         <class>Magento\UrlRewrite\Test\Page\Adminhtml\UrlrewriteEdit</class>
     </urlrewriteEdit>
-    <editCmsPage>
-        <mca>admin/urlrewrite/edit/cms_page</mca>
-        <area>adminhtml</area>
-        <class>Magento\UrlRewrite\Test\Page\Adminhtml\EditCmsPage</class>
-    </editCmsPage>
 </page>
diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/product_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..f00679e883ba6defaebe8f295c73ced6ab37a659
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_rollback.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/*
+ * Since the bundle product creation GUI doesn't allow to choose values for bundled products' custom options,
+ * bundled items should not contain products with required custom options.
+ * However, if to create such a bundle product, it will be always out of stock.
+ */
+require __DIR__ . '/../../../Magento/Catalog/_files/products_rollback.php';
+
+/** @var \Magento\Framework\Registry $registry */
+$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry');
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', true);
+
+/** @var $product \Magento\Catalog\Model\Product */
+$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Product');
+$product->load(3);
+if ($product->getId()) {
+    $product->delete();
+}
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', false);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php
index 7470225e2e921cba231859b9133f1c8089797d7b..99b99a25af28834c4396086fb3cc9b5a60cd02db 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php
@@ -62,4 +62,58 @@ class AttributeTest extends \Magento\Backend\Utility\Controller
 
         $this->assertTrue($isRedirectPresent);
     }
+
+
+    /**
+     * @covers \Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute::validateAction
+     *
+     * @dataProvider validateActionDataProvider
+     *
+     * @magentoDataFixture Magento/Catalog/_files/product_simple.php
+     * @magentoDataFixture Magento/Catalog/_files/product_simple_duplicated.php
+     */
+    public function testValidateActionWithMassUpdate($attributes)
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+
+        /** @var $session \Magento\Backend\Model\Session */
+        $session = $objectManager->get('Magento\Backend\Model\Session');
+        $session->setProductIds(array(1, 2));
+
+        $this->getRequest()->setParam('attributes', $attributes);
+
+        $this->dispatch('backend/catalog/product_action_attribute/validate/store/0');
+
+        $this->assertEquals(200, $this->getResponse()->getHttpResponseCode());
+
+        $response = $this->getResponse()->getBody();
+        $this->assertJson($response);
+        $data = json_decode($response, true);
+        $this->assertArrayHasKey('error', $data);
+        $this->assertFalse($data['error']);
+        $this->assertCount(1, $data);
+    }
+
+    /**
+     * Data Provider for validation
+     *
+     * @return array
+     */
+    public function validateActionDataProvider()
+    {
+        return array(
+            [
+                'arguments' => [
+                    'name'              => 'Name',
+                    'description'       => 'Description',
+                    'short_description' => 'Short Description',
+                    'price'             => '512',
+                    'weight'            => '16',
+                    'meta_title'        => 'Meta Title',
+                    'meta_keyword'      => 'Meta Keywords',
+                    'meta_description'  => 'Meta Description',
+                ],
+            ]
+        );
+    }
 }
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/_files/service_category_create.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/_files/service_category_create.php
new file mode 100644
index 0000000000000000000000000000000000000000..9b677ee90e22c725589114cff590cc230194f6cf
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/_files/service_category_create.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/_files/service_category_create_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/_files/service_category_create_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..d7a5bb4b1185ab40d3eeda90728bc2c782be8473
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/_files/service_category_create_rollback.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+use Magento\TestFramework\Helper\Bootstrap;
+
+/** @var \Magento\Framework\Registry $registry */
+$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry');
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', true);
+
+/** @var \Magento\Catalog\Model\Category $category */
+$category = Bootstrap::getObjectManager()->get('Magento\Catalog\Model\Category');
+$category = $category->loadByAttribute('url_key', 'test-category-name');
+
+if ($category && $category->getId()) {
+    $category->delete();
+}
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/_files/create_attribute_service.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/_files/create_attribute_service.php
new file mode 100644
index 0000000000000000000000000000000000000000..9b677ee90e22c725589114cff590cc230194f6cf
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/_files/create_attribute_service.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/_files/create_attribute_service_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/_files/create_attribute_service_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..a108926db18b9d3ea4b111132a738fd236f297a1
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/_files/create_attribute_service_rollback.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+use Magento\TestFramework\Helper\Bootstrap;
+
+/** @var \Magento\Framework\Registry $registry */
+$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry');
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', true);
+
+/** @var \Magento\Catalog\Model\Resource\Eav\Attribute $attribute */
+$attribute = Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Resource\Eav\Attribute');
+$attribute->loadByCode(4, 'label_attr_code3df4tr3');
+
+if ($attribute->getId()) {
+    $attribute->delete();
+}
+
+/** @var \Magento\Catalog\Model\Resource\Eav\Attribute $attribute */
+$attribute = Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Resource\Eav\Attribute');
+$attribute->loadByCode(4, 'test_attribute_code_l');
+
+if ($attribute->getId()) {
+    $attribute->delete();
+}
\ No newline at end of file
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/_files/service_product_create.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/_files/service_product_create.php
new file mode 100644
index 0000000000000000000000000000000000000000..9b677ee90e22c725589114cff590cc230194f6cf
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/_files/service_product_create.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/_files/service_product_create_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/_files/service_product_create_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..55dc7bed661b3c67c25528fbdec718e206b86888
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/_files/service_product_create_rollback.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+use Magento\TestFramework\Helper\Bootstrap;
+
+/** @var \Magento\Framework\Registry $registry */
+$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry');
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', true);
+
+/** @var \Magento\Catalog\Model\Product $productModel */
+$productModel = Bootstrap::getObjectManager()->get('Magento\Catalog\Model\Product');
+$productModel->load($productModel->getIdBySku('psku-test-1'));
+if ($productModel->getId()) {
+    $productModel->delete();
+}
+
+/** @var \Magento\Catalog\Model\Product $productModel */
+$productModel = Bootstrap::getObjectManager()->get('Magento\Catalog\Model\Product');
+$productModel->load($productModel->getIdBySku('psku-test-2'));
+if ($productModel->getId()) {
+    $productModel->delete();
+}
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Resource/Product/Indexer/Eav/SourceTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Resource/Product/Indexer/Eav/SourceTest.php
index 552c9afad59b9f0390d29e0e8e655f31a8916464..50627358db89ee2ee2574367e259c518a7bbd8cf 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Resource/Product/Indexer/Eav/SourceTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Resource/Product/Indexer/Eav/SourceTest.php
@@ -91,12 +91,12 @@ class SourceTest extends \PHPUnit_Framework_TestCase
 
         /** @var \Magento\Catalog\Model\Product $product1 **/
         $product1 = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Catalog\Model\Product');
-        $product1 = $product1->load($optionIds[0] * 10);
+        $product1 = $product1->load(10);
         $product1->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED)->save();
 
         /** @var \Magento\Catalog\Model\Product $product2 **/
         $product2 = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Catalog\Model\Product');
-        $product2 = $product2->load($optionIds[1] * 10);
+        $product2 = $product2->load(20);
         $product2->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED)->save();
 
         $result = $adapter->fetchAll($select);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_attribute.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_attribute.php
new file mode 100644
index 0000000000000000000000000000000000000000..51def5c764a8671353790077bb38fcebf94d7d33
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_attribute.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/** @var \Magento\Catalog\Model\Resource\Eav\Attribute $attribute */
+$attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
+    ->create('Magento\Catalog\Model\Resource\Eav\Attribute');
+$attribute->setAttributeCode('test_attribute_code_333')
+    ->setEntityTypeId(4)
+    ->setIsGlobal(1)
+    ->setPrice(95);
+$attribute->save();
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_attribute_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..796eeb55bf389502252290bdc6ce97b68896d10e
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_attribute_rollback.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/** @var \Magento\Framework\Registry $registry */
+$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry');
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', true);
+
+/** @var \Magento\Catalog\Model\Resource\Eav\Attribute $attribute */
+$attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
+    ->create('Magento\Catalog\Model\Resource\Eav\Attribute');
+
+$attribute->loadByCode(4, 'test_attribute_code_333');
+
+if ($attribute->getId()) {
+    $attribute->delete();
+}
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', false);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/products_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/products_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..0a1e74d031491c6014098ba5f9ca7085ddf0294f
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/products_rollback.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/** @var \Magento\Framework\Registry $registry */
+$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry');
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', true);
+
+/** @var $product \Magento\Catalog\Model\Product */
+$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Product');
+$product->load(1);
+if ($product->getId()) {
+    $product->delete();
+}
+
+/** @var $customDesignProduct \Magento\Catalog\Model\Product */
+$customDesignProduct = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
+    ->create('Magento\Catalog\Model\Product');
+$customDesignProduct->load(2);
+if ($customDesignProduct->getId()) {
+    $customDesignProduct->delete();
+}
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', false);
diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
index 5908f6749bf02ea117243a00403f1563ff328d06..5d2b8f9259108a3d9652c9d04f28ee00b9925434 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
@@ -183,17 +183,20 @@ class ProductTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * Tests adding of custom options with different behaviours
+     * Tests adding of custom options with existing and new product
      *
      * @param $behavior
      *
      * @magentoDataFixture Magento/Catalog/_files/product_simple.php
      * @dataProvider getBehaviorDataProvider
+     * @param string $behavior
+     * @param string $importFile
+     * @param string $sku
      */
-    public function testSaveCustomOptionsDuplicate($behavior)
+    public function testSaveCustomOptions($behavior, $importFile, $sku)
     {
         // import data from CSV file
-        $pathToFile = __DIR__ . '/_files/product_with_custom_options.csv';
+        $pathToFile = __DIR__ . '/_files/' . $importFile;
 
         $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
             ->create('Magento\Framework\App\Filesystem');
@@ -203,10 +206,10 @@ class ProductTest extends \PHPUnit_Framework_TestCase
         $this->_model->setSource($source)->setParameters(array('behavior' => $behavior))->isDataValid();
         $this->_model->importData();
 
-        $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
+        $productModel = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
             'Magento\Catalog\Model\Product'
         );
-        $product->load(1);
+        $product = $productModel->loadByAttribute('sku', $sku);
         // product from fixture
         $options = $product->getProductOptionsCollection();
 
@@ -462,8 +465,26 @@ class ProductTest extends \PHPUnit_Framework_TestCase
     public function getBehaviorDataProvider()
     {
         return array(
-            'Append behavior' => array('$behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND),
-            'Replace behavior' => array('$behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE)
+            'Append behavior with existing product' => array(
+                '$behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND,
+                '$importFile' => 'product_with_custom_options.csv',
+                '$sku' => 'simple'
+            ),
+            'Append behavior with new product' => array(
+                '$behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND,
+                '$importFile' => 'product_with_custom_options_new.csv',
+                '$sku' => 'simple_new'
+            ),
+            'Replace behavior with existing product' => array(
+                '$behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE,
+                '$importFile' => 'product_with_custom_options.csv',
+                '$sku' => 'simple'
+            ),
+            'Replace behavior with new product' => array(
+                '$behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE,
+                '$importFile' => 'product_with_custom_options_new.csv',
+                '$sku' => 'simple_new'
+            )
         );
     }
 
diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options_new.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options_new.csv
new file mode 100644
index 0000000000000000000000000000000000000000..9d6342ef458c69fafdffbfee9bc5e13d6f636960
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options_new.csv
@@ -0,0 +1,11 @@
+"sku","_store","_attribute_set","_type","_category","_root_category","_product_websites","color","cost","country_of_manufacture","created_at","custom_design","custom_design_from","custom_design_to","custom_layout_update","description","gallery","gift_message_available","has_options","image","image_label","manufacturer","media_gallery","meta_description","meta_keyword","meta_title","minimal_price","msrp","msrp_display_actual_price_type","msrp_enabled","name","news_from_date","news_to_date","options_container","page_layout","price","required_options","short_description","small_image","small_image_label","special_from_date","special_price","special_to_date","status","tax_class_id","thumbnail","thumbnail_label","updated_at","url_key","url_path","visibility","weight","qty","min_qty","use_config_min_qty","is_qty_decimal","backorders","use_config_backorders","min_sale_qty","use_config_min_sale_qty","max_sale_qty","use_config_max_sale_qty","is_in_stock","notify_stock_qty","use_config_notify_stock_qty","manage_stock","use_config_manage_stock","use_config_qty_increments","qty_increments","use_config_enable_qty_inc","enable_qty_increments","is_decimal_divided","_related_sku","_related_position","_crosssell_sku","_crosssell_position","_upsell_sku","_upsell_position","_associated_sku","_associated_default_qty","_associated_position","_tier_price_website","_tier_price_customer_group","_tier_price_qty","_tier_price_price","_group_price_website","_group_price_customer_group","_group_price_price","_media_attribute_id","_media_image","_media_label","_media_position","_media_is_disabled","_custom_option_store","_custom_option_type","_custom_option_title","_custom_option_is_required","_custom_option_price","_custom_option_sku","_custom_option_max_characters","_custom_option_sort_order","_custom_option_row_title","_custom_option_row_price","_custom_option_row_sku","_custom_option_row_sort"
+"simple_new",,"Default","simple",,,"base",,,,,,,,,,,,1,,,,,,,,,,,,"New Product",,,"Block after Info Column",,"10.0000",1,,,,,,,1,,,,"2012-07-13 12:04:17","new-product","new-product.html",4,,"100.0000","0.0000",1,0,0,1,"1.0000",1,"0.0000",1,1,,1,0,1,1,"0.0000",1,0,0,,,,,,,,,,,,,,,,,,,,,,,"field","Test Field",1,"1.0000","1-text",100,0,,,,
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,default,,"Test Field",,,,,,,,,
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"date_time","Test Date and Time",1,"2.0000","2-date",,0,,,,
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,default,,"Test Date and Time",,,,,,,,,
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"drop_down","New Select",1,,,,0,"Option 1","3.0000","3-1-select",0
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"Option 2","3.0000","3-2-select",0
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"default",,,,,,,,"Option 2",,,
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"radio","New Radio",1,,,,0,"Option 1","3.0000","4-1-radio",0
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"Option 2","3.0000","4-2-radio",0
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"default",,,,,,,,"Option 2",,,
diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config/MatrixTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config/MatrixTest.php
index d894a169d9ae37fb8e861657074953963a7fed2f..e2265a5e6d522d1c45a1ea9c38ffab775c20de4d 100644
--- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config/MatrixTest.php
+++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config/MatrixTest.php
@@ -23,28 +23,29 @@
  */
 namespace Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super\Config;
 
+use Magento\TestFramework\ObjectManager;
+
 /**
  * @magentoAppArea adminhtml
  */
-class MatrixTest extends \PHPUnit_Framework_TestCase
+class MatrixTest extends \Magento\Backend\Utility\Controller
 {
+    const ATTRIBUTE_LABEL = 'New Attribute Label';
+    const ATTRIBUTE_POSITION = 42;
+
     /**
      * @magentoAppIsolation enabled
      * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
      */
     public function testGetVariations()
     {
-        /** @var $objectManager \Magento\TestFramework\ObjectManager */
-        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-        $objectManager->get(
+        $this->_objectManager->get(
             'Magento\Framework\Registry'
         )->register(
             'current_product',
             \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
                 'Magento\Catalog\Model\Product'
-            )->load(
-                1
-            )
+            )->load(1)
         );
         \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
             'Magento\Framework\View\LayoutInterface'
@@ -86,4 +87,49 @@ class MatrixTest extends \PHPUnit_Framework_TestCase
             $variations
         );
     }
+
+    /**
+     * @magentoAppIsolation enabled
+     * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
+     */
+    public function testAttributesMergingByGetAttributesMethod()
+    {
+        $this->_objectManager->get(
+            'Magento\Framework\Registry'
+        )->register(
+            'current_product',
+            $this->_objectManager->create('Magento\Catalog\Model\Product')->load(1)
+        );
+        $this->_objectManager->get('Magento\Framework\View\LayoutInterface')
+            ->createBlock('Magento\Framework\View\Element\Text', 'head');
+        /** @var \Magento\Catalog\Model\Entity\Attribute $usedAttribute */
+        $usedAttribute = $this->_objectManager->get(
+            'Magento\Catalog\Model\Entity\Attribute'
+        )->loadByCode(
+            $this->_objectManager->get('Magento\Eav\Model\Config')
+                ->getEntityType('catalog_product')->getId(),
+            'test_configurable'
+        );
+        /** @var $block \Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super\Config */
+        $block = $this->_objectManager->get(
+            'Magento\Framework\View\LayoutInterface'
+        )->createBlock(
+            'Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super\Config'
+        );
+        $productData = array(
+            $usedAttribute->getId() => array(
+                'label'    => static::ATTRIBUTE_LABEL,
+                'position' => static::ATTRIBUTE_POSITION,
+            ),
+        );
+        $this->getRequest()->setParam('product', array('configurable_attributes_data' => $productData));
+        $attributes = $block->getAttributes();
+        $this->assertArrayHasKey($usedAttribute->getId(), $attributes);
+
+        $this->assertArrayHasKey('label', $attributes[$usedAttribute->getId()]);
+        $this->assertEquals(static::ATTRIBUTE_LABEL, $attributes[$usedAttribute->getId()]['label']);
+
+        $this->assertArrayHasKey('position', $attributes[$usedAttribute->getId()]);
+        $this->assertEquals(static::ATTRIBUTE_POSITION, $attributes[$usedAttribute->getId()]['position']);
+    }
 }
diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/ConfigTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/ConfigTest.php
index 36363d90d4eb696372a806ba8d1affaada83e9aa..9d13b8ea65549fd730865be052a1bd63da3d04c1 100644
--- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/ConfigTest.php
+++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/ConfigTest.php
@@ -23,26 +23,31 @@
  */
 namespace Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super;
 
+use Magento\Catalog\Model\Resource\Eav\Attribute;
+use Magento\TestFramework\ObjectManager;
+
 /**
  * @magentoAppArea adminhtml
  */
-class ConfigTest extends \PHPUnit_Framework_TestCase
+class ConfigTest extends \Magento\Backend\Utility\Controller
 {
+    const ATTRIBUTE_LABEL = 'New Attribute Label';
+    const ATTRIBUTE_POSITION = 42;
+
     /**
      * @magentoAppIsolation enabled
      */
     public function testGetSelectedAttributesForSimpleProductType()
     {
-        /** @var $objectManager \Magento\TestFramework\ObjectManager */
-        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-        $objectManager->get(
+        $this->_objectManager->get(
             'Magento\Framework\Registry'
         )->register(
             'current_product',
-            $objectManager->create('Magento\Catalog\Model\Product')
+            $this->_objectManager->create('Magento\Catalog\Model\Product')
         );
+
         /** @var $block \Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super\Config */
-        $block = $objectManager->get(
+        $block = $this->_objectManager->get(
             'Magento\Framework\View\LayoutInterface'
         )->createBlock(
             'Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super\Config'
@@ -56,35 +61,85 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
      */
     public function testGetSelectedAttributesForConfigurableProductType()
     {
-        /** @var $objectManager \Magento\TestFramework\ObjectManager */
-        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-        $objectManager->get(
+        $this->_objectManager->get(
             'Magento\Framework\Registry'
         )->register(
             'current_product',
-            $objectManager->create('Magento\Catalog\Model\Product')->load(1)
+            $this->_objectManager->create('Magento\Catalog\Model\Product')->load(1)
         );
-        $objectManager->get('Magento\Framework\View\LayoutInterface')
+        $this->_objectManager->get('Magento\Framework\View\LayoutInterface')
             ->createBlock('Magento\Framework\View\Element\Text', 'head');
-        $usedAttribute = $objectManager->get(
+        /** @var \Magento\Catalog\Model\Entity\Attribute $usedAttribute */
+        $usedAttribute = $this->_objectManager->get(
             'Magento\Catalog\Model\Entity\Attribute'
         )->loadByCode(
-            \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
+            $this->_objectManager->get(
                 'Magento\Eav\Model\Config'
             )->getEntityType(
-                'catalog_product'
-            )->getId(),
+                    'catalog_product'
+                )->getId(),
             'test_configurable'
         );
         /** @var $block \Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super\Config */
-        $block = $objectManager->get(
+        $block = $this->_objectManager->get(
             'Magento\Framework\View\LayoutInterface'
         )->createBlock(
             'Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super\Config'
         );
+        /** @var Attribute[] $selectedAttributes */
         $selectedAttributes = $block->getSelectedAttributes();
         $this->assertEquals(array($usedAttribute->getId()), array_keys($selectedAttributes));
+        /** @var Attribute $selectedAttribute */
         $selectedAttribute = reset($selectedAttributes);
         $this->assertEquals('test_configurable', $selectedAttribute->getAttributeCode());
     }
+
+    /**
+     * @magentoAppIsolation enabled
+     * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
+     */
+    public function testAttributesMergingByGetAttributesMethod()
+    {
+        $this->_objectManager->get(
+            'Magento\Framework\Registry'
+        )->register(
+            'current_product',
+            $this->_objectManager->create('Magento\Catalog\Model\Product')->load(1)
+        );
+        $this->_objectManager->get('Magento\Framework\View\LayoutInterface')
+            ->createBlock('Magento\Framework\View\Element\Text', 'head');
+        /** @var \Magento\Catalog\Model\Entity\Attribute $usedAttribute */
+        $usedAttribute = $this->_objectManager->get(
+            'Magento\Catalog\Model\Entity\Attribute'
+        )->loadByCode(
+            $this->_objectManager->get(
+                'Magento\Eav\Model\Config'
+            )->getEntityType(
+                    'catalog_product'
+                )->getId(),
+            'test_configurable'
+        );
+        /** @var $block \Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super\Config */
+        $block = $this->_objectManager->get(
+            'Magento\Framework\View\LayoutInterface'
+        )->createBlock(
+            'Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super\Config'
+        );
+        $productData = array(
+            $usedAttribute->getId() => array(
+                'label'    => static::ATTRIBUTE_LABEL,
+                'position' => static::ATTRIBUTE_POSITION,
+            ),
+
+        );
+        $this->getRequest()->setParam('product', array('configurable_attributes_data' => $productData));
+        $attributes = $block->getAttributes();
+        $this->assertArrayHasKey($usedAttribute->getId(), $attributes);
+
+        $this->assertArrayHasKey('label', $attributes[$usedAttribute->getId()]);
+        $this->assertEquals(static::ATTRIBUTE_LABEL, $attributes[$usedAttribute->getId()]['label']);
+
+        $this->assertArrayHasKey('position', $attributes[$usedAttribute->getId()]);
+        $this->assertEquals(static::ATTRIBUTE_POSITION, $attributes[$usedAttribute->getId()]['position']);
+    }
 }
diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php
index 5a529226aefacd8ad2ad5223ce925191deaf128f..a42f6ed3657359eed333daac8d995608b921bc86 100644
--- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php
+++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php
@@ -174,10 +174,7 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase
      */
     public function testGetParentIdsByChild()
     {
-        $attributes = $this->_model->getConfigurableAttributesAsArray($this->_product);
-        $attribute = reset($attributes);
-        $optionValueId = $attribute['values'][0]['value_index'];
-        $result = $this->_model->getParentIdsByChild($optionValueId * 10);
+        $result = $this->_model->getParentIdsByChild(10);
         // fixture
         $this->assertEquals(array(1), $result);
     }
@@ -248,7 +245,7 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase
             $this->_product
         );
         $this->assertInstanceOf('Magento\Catalog\Model\Product', $product);
-        $this->assertEquals("simple_{$optionValueId}", $product->getSku());
+        $this->assertEquals("simple_10", $product->getSku());
     }
 
     /**
diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute.php
index 697509c8e586b0c37cf3467787aea8925269e745..1e27312544cbbcaf86fbfe369f06132311804f40 100644
--- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute.php
+++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute.php
@@ -28,6 +28,7 @@ $installer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create
     'Magento\Catalog\Model\Resource\Setup',
     array('resourceName' => 'catalog_setup')
 );
+
 /** @var $attribute \Magento\Catalog\Model\Resource\Eav\Attribute */
 $attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
     'Magento\Catalog\Model\Resource\Eav\Attribute'
@@ -62,5 +63,10 @@ $attribute->setData(
 );
 $attribute->save();
 
+
 /* Assign attribute to attribute set */
 $installer->addAttributeToGroup('catalog_product', 'Default', 'General', $attribute->getId());
+
+/** @var \Magento\Eav\Model\Config $eavConfig */
+$eavConfig = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Eav\Model\Config');
+$eavConfig->clear();
diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..4120f5ba4625c23cf823687dd9bd30dd880758e1
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute_rollback.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/** @var \Magento\Eav\Model\Config $eavConfig */
+$eavConfig = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Eav\Model\Config');
+$attribute = $eavConfig->getAttribute('catalog_product', 'test_configurable');
+if ($attribute instanceof \Magento\Eav\Model\Entity\Attribute\AbstractAttribute
+    && $attribute->getId()
+) {
+    $attribute->delete();
+}
+$eavConfig->clear();
\ No newline at end of file
diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/delete_association.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/delete_association.php
new file mode 100644
index 0000000000000000000000000000000000000000..efe7eaddbec20288e84ec199cc972f0da5d02e14
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/delete_association.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/** @var $product \Magento\Catalog\Model\Product */
+$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Product');
+$product->load(1);
+$product->setAssociatedProductIds([20]);
+$product->save();
diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable.php
index 7a9e71d2604b12057ab73de58112cdbd080d3d73..9d256742d66031be03594a54b637f19bad9c695a 100644
--- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable.php
+++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable.php
@@ -39,21 +39,24 @@ $options->setAttributeFilter($attribute->getId());
 
 $attributeValues = array();
 $productIds = array();
+$attributeSetId = $installer->getAttributeSetId('catalog_product', 'Default');
+$productIds = array(10, 20);
 foreach ($options as $option) {
     /** @var $product \Magento\Catalog\Model\Product */
     $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Product');
+    $productId = array_shift($productIds);
     $product->setTypeId(
         \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE
     )->setId(
-        $option->getId() * 10
+        $productId
     )->setAttributeSetId(
-        $installer->getAttributeSetId('catalog_product', 'Default')
+        $attributeSetId
     )->setWebsiteIds(
         array(1)
     )->setName(
         'Configurable Option' . $option->getId()
     )->setSku(
-        'simple_' . $option->getId()
+        'simple_' . $productId
     )->setPrice(
         10
     )->setTestConfigurable(
@@ -65,6 +68,7 @@ foreach ($options as $option) {
     )->setStockData(
         array('use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1)
     )->save();
+
     $attributeValues[] = array(
         'label' => 'test',
         'attribute_id' => $attribute->getId(),
@@ -82,7 +86,7 @@ $product->setTypeId(
 )->setId(
     1
 )->setAttributeSetId(
-    $installer->getAttributeSetId('catalog_product', 'Default')
+    $attributeSetId
 )->setWebsiteIds(
     array(1)
 )->setName(
diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_rollback.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..6c40df5c6473bbdeb8d31d5eded59fe3bbbde782
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_rollback.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/** @var \Magento\Framework\Registry $registry */
+$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry');
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', true);
+
+/** @var $product \Magento\Catalog\Model\Product */
+$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Product');
+$product->load(10);
+if ($product->getId()) {
+    $product->delete();
+}
+$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Product');
+$product->load(20);
+if ($product->getId()) {
+    $product->delete();
+}
+$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Product');
+$product->load(1);
+if ($product->getId()) {
+    $product->delete();
+}
+
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', false);
+
+require __DIR__ . '/configurable_attribute_rollback.php';
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Account/Dashboard/HelloTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Account/Dashboard/HelloTest.php
index b40d064667bc50aa9a869679af40eced55994cb4..3c7daefce8b7fbd71aec1b06424fcf48f6370075 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Block/Account/Dashboard/HelloTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Account/Dashboard/HelloTest.php
@@ -83,7 +83,7 @@ class HelloTest extends \PHPUnit_Framework_TestCase
     {
         $this->customerSession->setCustomerId(1);
         $html = $this->block->toHtml();
-        $this->assertContains("<div class=\"block dashboard welcome\">", $html);
+        $this->assertContains("<div class=\"block block-dashboard-welcome\">", $html);
         $this->assertContains("<strong>Hello, Firstname Lastname!</strong>", $html);
     }
 }
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php
index 4df8fdb2486a8b0944ae22b62c93245e51463dc7..2cd653e6033e195621fa1acd054b63dc54b648c1 100755
--- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php
@@ -53,7 +53,7 @@ class AccountTest extends \Magento\TestFramework\TestCase\AbstractController
         $this->dispatch('customer/account/index');
 
         $body = $this->getResponse()->getBody();
-        $this->assertContains('<div class="block dashboard welcome">', $body);
+        $this->assertContains('<div class="block block-dashboard-welcome">', $body);
         $this->assertContains('Hello, Firstname Lastname!', $body);
         $this->assertContains('Green str, 67', $body);
     }
diff --git a/dev/tests/integration/testsuite/Magento/Fedex/Model/CarrierTest.php b/dev/tests/integration/testsuite/Magento/Fedex/Model/CarrierTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e3044e617cd2d241820266f25421846d13e6ddf3
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Fedex/Model/CarrierTest.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Fedex\Model;
+
+class CarrierTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Fedex\Model\Carrier
+     */
+    protected $_model;
+
+    protected function setUp()
+    {
+        $this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
+            'Magento\Fedex\Model\Carrier'
+        );
+    }
+
+    /**
+     * @dataProvider getCodeDataProvider
+     * @param string $type
+     * @param int $expectedCount
+     */
+    public function testGetCode($type, $expectedCount)
+    {
+        $result = $this->_model->getCode($type);
+        $this->assertCount($expectedCount, $result);
+    }
+
+    /**
+     * Data Provider for testGetCode
+     * @return array
+     */
+    public function getCodeDataProvider()
+    {
+        return array(
+            array('method', 21),
+            array('dropoff', 5),
+            array('packaging', 7),
+            array('containers_filter', 4),
+            array('delivery_confirmation_types', 4),
+            array('unit_of_measure', 2),
+        );
+    }
+
+    /**
+     * @dataProvider getCodeUnitOfMeasureDataProvider
+     * @param string $code
+     */
+    public function testGetCodeUnitOfMeasure($code)
+    {
+        $result = $this->_model->getCode('unit_of_measure', $code);
+        $this->assertNotEmpty($result);
+    }
+
+    /**
+     * Data Provider for testGetCodeUnitOfMeasure
+     * @return array
+     */
+    public function getCodeUnitOfMeasureDataProvider()
+    {
+        return array(
+            array('LB'),
+            array('KG'),
+        );
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Fedex/Model/Source/UnitofmeasureTest.php b/dev/tests/integration/testsuite/Magento/Fedex/Model/Source/UnitofmeasureTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..49ce870dbdd362d770c66ec20545b5faa6682a6a
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Fedex/Model/Source/UnitofmeasureTest.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Fedex\Model\Source;
+
+class UnitofmeasureTest extends \PHPUnit_Framework_TestCase
+{
+    public function testToOptionArray()
+    {
+        /** @var $model \Magento\Fedex\Model\Source\Unitofmeasure */
+        $model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
+            'Magento\Fedex\Model\Source\Unitofmeasure'
+        );
+        $result = $model->toOptionArray();
+        $this->assertCount(2, $result);
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/GoogleShopping/Controller/Adminhtml/GoogleShopping/TypesTest.php b/dev/tests/integration/testsuite/Magento/GoogleShopping/Controller/Adminhtml/GoogleShopping/TypesTest.php
index f1945c148ec3e792a4bb14b494aef9ccdee6e6b8..99133c4392377f0bd5f27f91e29322123de43ae7 100644
--- a/dev/tests/integration/testsuite/Magento/GoogleShopping/Controller/Adminhtml/GoogleShopping/TypesTest.php
+++ b/dev/tests/integration/testsuite/Magento/GoogleShopping/Controller/Adminhtml/GoogleShopping/TypesTest.php
@@ -34,4 +34,23 @@ class TypesTest extends \Magento\Backend\Utility\Controller
         $body = $this->getResponse()->getBody();
         $this->assertSelectCount('[data-role="row"]', 1, $body, 'Grid with row exists');
     }
+
+    public function testLoadAttributeSetsAction()
+    {
+        $this->dispatch('backend/admin/googleshopping_types/loadAttributeSets/');
+        $body = $this->getResponse()->getBody();
+
+        $this->assertTag(
+            array(
+                'tag'        => 'select',
+                'attributes' => array('name' => 'attribute_set_id'),
+                'descendant' => array(
+                    'tag'    => 'option',
+                    'attributes' => array('value' => 4),
+                    'content' => 'Default',
+                )
+            ),
+            $body
+        );
+    }
 }
diff --git a/dev/tests/integration/testsuite/Magento/GoogleShopping/Model/Attribute/TaxTest.php b/dev/tests/integration/testsuite/Magento/GoogleShopping/Model/Attribute/TaxTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4cf0b75d35d711d530e0685092ab3bd7b0675008
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/GoogleShopping/Model/Attribute/TaxTest.php
@@ -0,0 +1,335 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\GoogleShopping\Model\Attribute;
+
+use Magento\Tax\Model\ClassModel;
+use Magento\Tax\Service\V1\Data\TaxRuleBuilder;
+use Magento\Tax\Service\V1\Data\TaxRateBuilder;
+use Magento\Tax\Service\V1\TaxRuleFixtureFactory;
+
+/**
+ * Tests GoogleShopping\Model\Attribute\Tax
+ */
+class TaxTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\GoogleShopping\Model\Attribute\Tax
+     */
+    protected $googleShoppingTaxAttribute;
+
+    /**
+     * @var \Magento\Framework\ObjectManager
+     */
+    protected $objectManager;
+
+    /**
+     * TaxRule builder
+     *
+     * @var TaxRuleBuilder
+     */
+    private $taxRuleBuilder;
+
+    /**
+     * TaxRate builder
+     *
+     * @var TaxRateBuilder
+     */
+    private $taxRateBuilder;
+
+    /**
+     * TaxRuleService
+     *
+     * @var \Magento\Tax\Service\V1\TaxRuleServiceInterface
+     */
+    private $taxRuleService;
+
+    /**
+     * Helps in creating required tax rules.
+     *
+     * @var TaxRuleFixtureFactory
+     */
+    private $taxRuleFixtureFactory;
+
+    /**
+     * Array of default tax classes ids
+     *
+     * Key is class name
+     *
+     * @var int[]
+     */
+    private $taxClasses;
+
+    /**
+     * Array of default tax rates ids.
+     *
+     * Key is rate percentage as string.
+     *
+     * @var int[]
+     */
+    private $taxRates;
+
+    /**
+     * Array of default tax rules ids.
+     *
+     * Key is rule code.
+     *
+     * @var int[]
+     */
+    private $taxRules;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->googleShoppingTaxAttribute = $this->objectManager
+            ->create('Magento\GoogleShopping\Model\Attribute\Tax');
+        $this->taxRateBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxRuleBuilder');
+        $this->taxRuleService = $this->objectManager->get('Magento\Tax\Service\V1\TaxRuleServiceInterface');
+        $this->taxRuleBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxRuleBuilder');
+        $this->taxRuleFixtureFactory = new TaxRuleFixtureFactory();
+        $this->setUpDefaultRules();
+    }
+
+    /**
+     * @magentoDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testConvertAttributeWithSimpleProduct()
+    {
+        $defaultProductTaxClassProduct = $this->objectManager->create('Magento\Catalog\Model\Product');
+        $defaultProductTaxClassProduct->load(1);
+        $defaultProductTaxClassProduct->setTaxClassId($this->taxClasses['DefaultProductClass']);
+
+        $defaultGoogleShoppingEntry = $this->objectManager
+            ->create('Magento\Framework\Gdata\Gshopping\Entry');
+        $defaultEntry = $this->googleShoppingTaxAttribute
+            ->convertAttribute($defaultProductTaxClassProduct, $defaultGoogleShoppingEntry);
+
+        $this->assertEquals(2, count($defaultEntry->getTaxes()));
+
+        foreach ($defaultEntry->getTaxes() as $tax) {
+            $this->assertEquals('US', $tax->__get('tax_country'));
+            $this->assertEquals(7.5, round($tax->__get('tax_rate'), 1));
+            $this->assertTrue($tax->__get('tax_region') == 'NM' || $tax->__get('tax_region') == 'CA');
+        }
+
+        $higherProductTaxClassProduct = $this->objectManager->create('Magento\Catalog\Model\Product');
+        $higherProductTaxClassProduct->load(1);
+        $higherProductTaxClassProduct->setTaxClassId($this->taxClasses['HigherProductClass']);
+
+        $higherGoogleShoppingEntry = $this->objectManager
+            ->create('Magento\Framework\Gdata\Gshopping\Entry');
+        $higherEntry = $this->googleShoppingTaxAttribute
+            ->convertAttribute($higherProductTaxClassProduct, $higherGoogleShoppingEntry);
+
+        $this->assertEquals(2, count($higherEntry->getTaxes()));
+
+        foreach ($higherEntry->getTaxes() as $tax) {
+            $this->assertEquals('US', $tax->__get('tax_country'));
+            if ($tax->__get('tax_region') == 'NM') {
+                $this->assertEquals(22.0, round($tax->__get('tax_rate'), 1));
+            } elseif ($tax->__get('tax_region') == 'CA') {
+                $this->assertEquals(10.0, round($tax->__get('tax_rate'), 1));
+            } else {
+                $this->fail('Invalid tax region');
+            }
+        }
+    }
+
+    /**
+     * @magentoDataFixture Magento/Catalog/_files/product_group_prices.php
+     */
+    public function testConvertAttributeWithProductGroup()
+    {
+        $defaultProductTaxClassProduct = $this->objectManager->create('Magento\Catalog\Model\Product');
+        $defaultProductTaxClassProduct->load(1);
+        $defaultProductTaxClassProduct->setTaxClassId($this->taxClasses['DefaultProductClass']);
+
+        $defaultGoogleShoppingEntry = $this->objectManager
+            ->create('Magento\Framework\Gdata\Gshopping\Entry');
+        $defaultEntry = $this->googleShoppingTaxAttribute
+            ->convertAttribute($defaultProductTaxClassProduct, $defaultGoogleShoppingEntry);
+
+        $this->assertEquals(2, count($defaultEntry->getTaxes()));
+
+        foreach ($defaultEntry->getTaxes() as $tax) {
+            $this->assertEquals('US', $tax->__get('tax_country'));
+            $this->assertEquals(7.5, round($tax->__get('tax_rate'), 1));
+            $this->assertTrue($tax->__get('tax_region') == 'NM' || $tax->__get('tax_region') == 'CA');
+        }
+
+        $higherProductTaxClassProduct = $this->objectManager->create('Magento\Catalog\Model\Product');
+        $higherProductTaxClassProduct->load(1);
+        $higherProductTaxClassProduct->setTaxClassId($this->taxClasses['HigherProductClass']);
+
+        $higherGoogleShoppingEntry = $this->objectManager
+            ->create('Magento\Framework\Gdata\Gshopping\Entry');
+        $higherEntry = $this->googleShoppingTaxAttribute
+            ->convertAttribute($higherProductTaxClassProduct, $higherGoogleShoppingEntry);
+
+        $this->assertEquals(2, count($higherEntry->getTaxes()));
+
+        foreach ($higherEntry->getTaxes() as $tax) {
+            $this->assertEquals('US', $tax->__get('tax_country'));
+            if ($tax->__get('tax_region') == 'NM') {
+                $this->assertEquals(22.0, round($tax->__get('tax_rate'), 1));
+            } elseif ($tax->__get('tax_region') == 'CA') {
+                $this->assertEquals(10.0, round($tax->__get('tax_rate'), 1));
+            } else {
+                $this->fail('Invalid tax region');
+            }
+        }
+    }
+
+    /**
+     * @magentoDataFixture Magento/Catalog/_files/multiple_products.php
+     */
+    public function testConvertAttributeWithMultipleProducts()
+    {
+        $productA = $this->objectManager->create('Magento\Catalog\Model\Product');
+        $productA->load(10);
+        $productA->setTaxClassId($this->taxClasses['DefaultProductClass']);
+        $productAGoogleShoppingEntry = $this->objectManager
+            ->create('Magento\Framework\Gdata\Gshopping\Entry');
+        $productAEntry = $this->googleShoppingTaxAttribute
+            ->convertAttribute($productA, $productAGoogleShoppingEntry);
+
+        $this->assertEquals(2, count($productAEntry->getTaxes()));
+        foreach ($productAEntry->getTaxes() as $tax) {
+            $this->assertEquals('US', $tax->__get('tax_country'));
+            $this->assertEquals(7.5, round($tax->__get('tax_rate'), 1));
+            $this->assertTrue($tax->__get('tax_region') == 'NM' || $tax->__get('tax_region') == 'CA');
+        }
+
+        $productB = $this->objectManager->create('Magento\Catalog\Model\Product');
+        $productB->load(11);
+        $productB->setTaxClassId($this->taxClasses['HigherProductClass']);
+        $productBGoogleShoppingEntry = $this->objectManager
+            ->create('Magento\Framework\Gdata\Gshopping\Entry');
+        $productBEntry = $this->googleShoppingTaxAttribute
+            ->convertAttribute($productB, $productBGoogleShoppingEntry);
+
+        $this->assertEquals(2, count($productBEntry->getTaxes()));
+        foreach ($productBEntry->getTaxes() as $tax) {
+            $this->assertEquals('US', $tax->__get('tax_country'));
+            if ($tax->__get('tax_region') == 'NM') {
+                $this->assertEquals(22.0, round($tax->__get('tax_rate'), 1));
+            } elseif ($tax->__get('tax_region') == 'CA') {
+                $this->assertEquals(10.0, round($tax->__get('tax_rate'), 1));
+            } else {
+                $this->fail('Invalid tax region');
+            }
+        }
+
+        $productC = $this->objectManager->create('Magento\Catalog\Model\Product');
+        $productC->load(12);
+        $productC->setTaxClassId($this->taxClasses['HighestProductClass']);
+        $productCGoogleShoppingEntry = $this->objectManager
+            ->create('Magento\Framework\Gdata\Gshopping\Entry');
+        $productCEntry = $this->googleShoppingTaxAttribute
+            ->convertAttribute($productC, $productCGoogleShoppingEntry);
+
+        $this->assertEquals(2, count($productCEntry->getTaxes()));
+        foreach ($productCEntry->getTaxes() as $tax) {
+            $this->assertEquals('US', $tax->__get('tax_country'));
+            if ($tax->__get('tax_region') == 'NM') {
+                $this->assertEquals(22.5, round($tax->__get('tax_rate'), 1));
+            } elseif ($tax->__get('tax_region') == 'CA') {
+                $this->assertEquals(15.0, round($tax->__get('tax_rate'), 1));
+            } else {
+                $this->fail('Invalid tax_region');
+            }
+        }
+    }
+
+    /**
+     * Helper function that sets up some default rules
+     */
+    private function setUpDefaultRules()
+    {
+        $this->taxClasses = $this->taxRuleFixtureFactory->createTaxClasses([
+            ['name' => 'DefaultCustomerClass', 'type' => ClassModel::TAX_CLASS_TYPE_CUSTOMER],
+            ['name' => 'DefaultProductClass', 'type' => ClassModel::TAX_CLASS_TYPE_PRODUCT],
+            ['name' => 'HigherProductClass', 'type' => ClassModel::TAX_CLASS_TYPE_PRODUCT],
+            ['name' => 'HighestProductClass', 'type' => ClassModel::TAX_CLASS_TYPE_PRODUCT],
+        ]);
+
+        $this->taxRates = $this->taxRuleFixtureFactory->createTaxRates([
+            ['percentage' => 7.5, 'country' => 'US', 'region' => 42],
+            ['percentage' => 7.5, 'country' => 'US', 'region' => 12], // Default store rate
+            ['percentage' => 10, 'country' => 'MX', 'region' => 99],
+        ]);
+
+        $higherRates = $this->taxRuleFixtureFactory->createTaxRates([
+            ['percentage' => 22, 'country' => 'US', 'region' => 42],
+            ['percentage' => 10, 'country' => 'US', 'region' => 12], // Default store rate
+            ['percentage' => 15, 'country' => 'MX', 'region' => 99],
+        ]);
+
+        $highestRates = $this->taxRuleFixtureFactory->createTaxRates([
+            ['percentage' => 22.5, 'country' => 'US', 'region' => 42],
+            ['percentage' => 15, 'country' => 'US', 'region' => 12], // Default store rate
+            ['percentage' => 20, 'country' => 'MX', 'region' => 99],
+        ]);
+
+        $this->taxRules = $this->taxRuleFixtureFactory->createTaxRules([
+            [
+                'code' => 'Default Rule',
+                'customer_tax_class_ids' => [$this->taxClasses['DefaultCustomerClass'], 3],
+                'product_tax_class_ids' => [$this->taxClasses['DefaultProductClass']],
+                'tax_rate_ids' => array_values($this->taxRates),
+                'sort_order' => 0,
+                'priority' => 0,
+            ],
+            [
+                'code' => 'Higher Rate Rule',
+                'customer_tax_class_ids' => [$this->taxClasses['DefaultCustomerClass'], 3],
+                'product_tax_class_ids' => [$this->taxClasses['HigherProductClass']],
+                'tax_rate_ids' => array_values($higherRates),
+                'sort_order' => 0,
+                'priority' => 0,
+            ],
+            [
+                'code' => 'Highest Rate Rule',
+                'customer_tax_class_ids' => [$this->taxClasses['DefaultCustomerClass'], 3],
+                'product_tax_class_ids' => [$this->taxClasses['HighestProductClass']],
+                'tax_rate_ids' => array_values($highestRates),
+                'sort_order' => 1,
+                'priority' => 1,
+            ],
+        ]);
+
+        // For cleanup
+        $this->taxRates = array_merge($this->taxRates, $higherRates, $highestRates);
+    }
+
+    /**
+     * Helper function that tears down some default rules
+     */
+    public function tearDown()
+    {
+        $this->taxRuleFixtureFactory->deleteTaxRules(array_values($this->taxRules));
+        $this->taxRuleFixtureFactory->deleteTaxRates(array_values($this->taxRates));
+        $this->taxRuleFixtureFactory->deleteTaxClasses(array_values($this->taxClasses));
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Multishipping/Controller/CheckoutTest.php b/dev/tests/integration/testsuite/Magento/Multishipping/Controller/CheckoutTest.php
index 29a06b99a55515fb466a3957da54579817f1c59e..f912c1b0b5d15a8fa03cd032edb588511b36d2f1 100644
--- a/dev/tests/integration/testsuite/Magento/Multishipping/Controller/CheckoutTest.php
+++ b/dev/tests/integration/testsuite/Magento/Multishipping/Controller/CheckoutTest.php
@@ -50,6 +50,7 @@ class CheckoutTest extends \Magento\TestFramework\TestCase\AbstractController
         )->setQuoteId(
             $quote->getId()
         );
+        $formKey = $this->_objectManager->get('Magento\Framework\Data\Form\FormKey');
         $logger = $this->getMock('Magento\Framework\Logger', array(), array(), '', false);
         /** @var $session \Magento\Customer\Model\Session */
         $session = Bootstrap::getObjectManager()->create('Magento\Customer\Model\Session', array($logger));
@@ -67,5 +68,6 @@ class CheckoutTest extends \Magento\TestFramework\TestCase\AbstractController
             $html
         );
         $this->assertContains('<span class="price">$10.00</span>', $html);
+        $this->assertContains('<input name="form_key" type="hidden" value="' . $formKey->getFormKey(), $html);
     }
 }
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php
index c52c685aa57221a188d801cabaabff4fc03eecc6..78541ca25939e1efa227b2b53e3fe7f72abbca9c 100644
--- a/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php
+++ b/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php
@@ -248,14 +248,9 @@ class CheckoutTest extends \PHPUnit_Framework_TestCase
         $checkoutModel->returnFromPaypal('token');
 
         $billingAddress = $quote->getBillingAddress();
-        $this->assertEquals($billingAddress->getEmail(), $quote->getCustomerEmail());
-        $this->assertEquals($billingAddress->getPrefix(), $quote->getCustomerPrefix());
-        $this->assertEquals($billingAddress->getFirstname(), $quote->getCustomerFirstname());
-        $this->assertEquals($billingAddress->getMiddlename(), $quote->getCustomerMiddlename());
-        $this->assertEquals($billingAddress->getLastname(), $quote->getCustomerLastname());
-        $this->assertEquals($billingAddress->getSuffix(), $quote->getCustomerSuffix());
-        $this->assertTrue($billingAddress->getShouldIgnoreValidation());
+
         $this->assertContains('exported', $billingAddress->getFirstname());
+        $this->assertEquals('note', $billingAddress->getCustomerNote());
 
         $shippingAddress = $quote->getShippingAddress();
         $this->assertTrue((bool)$shippingAddress->getSameAsBilling());
@@ -293,6 +288,7 @@ class CheckoutTest extends \PHPUnit_Framework_TestCase
         }
         $fixture = new \Magento\Framework\Object($result);
         $fixture->setExportedKeys($addressDataKeys);
+        $fixture->setData('note', 'note');
         return $fixture;
     }
 
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Model/PayflowproTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Model/PayflowproTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f68eefd2abe65ccaacb1b2bd333d42357cfa5aaa
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Paypal/Model/PayflowproTest.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Model;
+
+class PayflowproTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\ObjectManager
+     */
+    protected $_objectManager;
+
+    /**
+     * @var \Magento\Paypal\Model\Payflowpro
+     */
+    protected $_model;
+
+    /**
+     * @var \Magento\Framework\HTTP\ZendClient
+     */
+    protected $_httpClientMock;
+
+    public function setUp()
+    {
+        $this->_objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $httpClientFactoryMock = $this->getMockBuilder('Magento\Framework\HTTP\ZendClientFactory')
+            ->setMethods(['create'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->_httpClientMock = $this->getMockBuilder('Magento\Framework\HTTP\ZendClient')->setMethods([])
+            ->disableOriginalConstructor()->getMock();
+        $this->_httpClientMock->expects($this->any())->method('setUri')->will($this->returnSelf());
+        $this->_httpClientMock->expects($this->any())->method('setConfig')->will($this->returnSelf());
+        $this->_httpClientMock->expects($this->any())->method('setMethod')->will($this->returnSelf());
+        $this->_httpClientMock->expects($this->any())->method('setParameterPost')->will($this->returnSelf());
+        $this->_httpClientMock->expects($this->any())->method('setHeaders')->will($this->returnSelf());
+        $this->_httpClientMock->expects($this->any())->method('setUrlEncodeBody')->will($this->returnSelf());
+
+        $httpClientFactoryMock->expects($this->any())->method('create')
+            ->will($this->returnValue($this->_httpClientMock));
+
+        $this->_model = $this->_objectManager->create(
+            'Magento\Paypal\Model\Payflowpro',
+            ['httpClientFactory' => $httpClientFactoryMock]
+        );
+    }
+
+    /**
+     * @magentoDataFixture Magento/Sales/_files/order_paid_with_payflowpro.php
+     */
+    public function testReviewPaymentNullResponce()
+    {
+        /** @var \Magento\Sales\Model\Order $order */
+        $order = $this->_objectManager->create('Magento\Sales\Model\Order');
+        $order->loadByIncrementId('100000001');
+
+        $this->_httpClientMock->expects($this->any())->method('request')
+            ->will($this->returnValue(new \Magento\Framework\Object(['body' => 'RESULTval=12&val2=34'])));
+        $expectedResult = ['resultval' => '12', 'val2' => '34', 'result_code' => null, 'respmsg' => null];
+
+        $this->assertEquals($expectedResult, $this->_model->acceptPayment($order->getPayment()));
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Model/VoidTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Model/VoidTest.php
index 35a37a47b00187d7f64548e49f3777a1568edf87..00de2fc305a6fa6de728edae3dc7e23be243264a 100644
--- a/dev/tests/integration/testsuite/Magento/Paypal/Model/VoidTest.php
+++ b/dev/tests/integration/testsuite/Magento/Paypal/Model/VoidTest.php
@@ -43,6 +43,10 @@ class VoidTest extends \PHPUnit_Framework_TestCase
         $storeManager = $objectManager->get('Magento\Store\Model\StoreManagerInterface');
         $configFactory = $objectManager->get('Magento\Paypal\Model\ConfigFactory');
         $mathRandom = $objectManager->get('Magento\Framework\Math\Random');
+        $httpClientFactoryMock = $this->getMockBuilder('Magento\Framework\HTTP\ZendClientFactory')
+            ->setMethods(['create'])
+            ->disableOriginalConstructor()
+            ->getMock();
 
         /** @var $order \Magento\Sales\Model\Order */
         $order = $objectManager->create('Magento\Sales\Model\Order');
@@ -64,7 +68,8 @@ class VoidTest extends \PHPUnit_Framework_TestCase
                 $centinelService,
                 $storeManager,
                 $configFactory,
-                $mathRandom
+                $mathRandom,
+                $httpClientFactoryMock
             )
         );
 
diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php
index 53d0573346a934b6d7b8ec6f16446be8c28096d1..d18c0c11578f9d6dfc697bab8f2e932ce2c2d75d 100644
--- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php
+++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php
@@ -107,12 +107,13 @@ class CreateTest extends \Magento\Backend\Utility\Controller
         $order->addProducts(array(1 => array('qty' => 1)));
         $this->dispatch('backend/sales/order_create/index');
         $html = $this->getResponse()->getBody();
-        $this->assertContains('<div id="order-customer-selector"', $html);
-        $this->assertContains('<div id="sales_order_create_customer_grid">', $html);
-        $this->assertContains('<div id="order-billing_method_form">', $html);
-        $this->assertContains('id="shipping-method-overlay"', $html);
-        $this->assertContains('<div id="sales_order_create_search_grid">', $html);
-        $this->assertContains('id="coupons:code"', $html);
+
+        $this->assertSelectCount('div#order-customer-selector', true, $html);
+        $this->assertSelectCount('[data-grid-id=sales_order_create_customer_grid]', true, $html);
+        $this->assertSelectCount('div#order-billing_method_form', true, $html);
+        $this->assertSelectCount('#shipping-method-overlay', true, $html);
+        $this->assertSelectCount('div#sales_order_create_search_grid', true, $html);
+        $this->assertSelectCount('#coupons:code', true, $html);
     }
 
     /**
diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Resource/Report/Bestsellers/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Resource/Report/Bestsellers/CollectionTest.php
index b47c2f127e85e83970a7af82bc8a37932627de01..ad8874a03aab6bf7085bb1ae7ad431a60b890fc4 100644
--- a/dev/tests/integration/testsuite/Magento/Sales/Model/Resource/Report/Bestsellers/CollectionTest.php
+++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Resource/Report/Bestsellers/CollectionTest.php
@@ -52,4 +52,89 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
         }
         $this->assertEquals($expectedResult, $actualResult);
     }
+
+    /**
+     * @dataProvider tableForPeriodDataProvider
+     *
+     * @param $period
+     * @param $expectedTable
+     * @param $dateFrom
+     * @param $dateTo
+     */
+    public function testTableSelection($period, $expectedTable, $dateFrom, $dateTo)
+    {
+        $dbTableName = $this->_collection->getTable($expectedTable);
+        $this->_collection->setPeriod($period);
+        $this->_collection->setDateRange($dateFrom, $dateTo);
+        $this->_collection->load();
+        $from = $this->_collection->getSelect()->getPart('from');
+
+        $this->assertArrayHasKey($dbTableName, $from);
+
+        $this->assertArrayHasKey('tableName', $from[$dbTableName]);
+        $actualTable = $from[$dbTableName]['tableName'];
+
+        $this->assertEquals($dbTableName, $actualTable);
+    }
+
+    /**
+     * Data provider for testTableSelection
+     *
+     * @return array
+     */
+    public function tableForPeriodDataProvider()
+    {
+        $dateNow = date('Y-m-d', time());
+        $dateYearAgo = date('Y-m-d', strtotime($dateNow . ' -1 year'));
+        return array(
+            [
+                'period'    => 'year',
+                'table'     => 'sales_bestsellers_aggregated_yearly',
+                'date_from' => null,
+                'date_to'   => null
+            ],
+            [
+                'period'    => 'month',
+                'table'     => 'sales_bestsellers_aggregated_monthly',
+                'date_from' => null,
+                'date_to'   => null
+            ],
+            [
+                'period'    => 'day',
+                'table'     => 'sales_bestsellers_aggregated_daily',
+                'date_from' => null,
+                'date_to'   => null
+            ],
+            [
+                'period'    => 'undefinedPeriod',
+                'table'     => 'sales_bestsellers_aggregated_daily',
+                'date_from' => null,
+                'date_to'   => null
+            ],
+            [
+                'period'    => null,
+                'table'     => 'sales_bestsellers_aggregated_daily',
+                'date_from' => $dateYearAgo,
+                'date_to'   => $dateNow
+            ],
+            [
+                'period'    => null,
+                'table'     => 'sales_bestsellers_aggregated_daily',
+                'date_from' => $dateNow,
+                'date_to'   => $dateNow
+            ],
+            [
+                'period'    => null,
+                'table'     => 'sales_bestsellers_aggregated_daily',
+                'date_from' => $dateYearAgo,
+                'date_to'   => $dateYearAgo
+            ],
+            [
+                'period'    => null,
+                'table'     => 'sales_bestsellers_aggregated_yearly',
+                'date_from' => null,
+                'date_to'   => null
+            ],
+        );
+    }
 }
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Pricing/Price/Plugin/AttributePriceTest.php b/dev/tests/integration/testsuite/Magento/Tax/Pricing/Price/Plugin/AttributePriceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f1ae5b55957db737217535299d9a3676b6dc7ac4
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/Pricing/Price/Plugin/AttributePriceTest.php
@@ -0,0 +1,208 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Pricing\Price\Plugin;
+
+use Magento\Tax\Model\ClassModel;
+use Magento\Tax\Service\V1\TaxRuleFixtureFactory;
+use Magento\Store\Model\ScopeInterface;
+use Magento\Tax\Model\Config;
+
+/**
+ * @magentoDataFixture Magento/Customer/_files/customer.php
+ * @magentoDataFixture Magento/Customer/_files/customer_address.php
+ * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
+ */
+class AttributePriceTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * Array of default tax classes ids
+     *
+     * Key is class name
+     *
+     * @var int[]
+     */
+    private $taxClasses;
+
+    /**
+     * Array of default tax rates ids.
+     *
+     * Key is rate percentage as string.
+     *
+     * @var int[]
+     */
+    private $taxRates;
+
+    /**
+     * Array of default tax rules ids.
+     *
+     * Key is rule code.
+     *
+     * @var int[]
+     */
+    private $taxRules;
+
+    /**
+     * Helps in creating required tax rules.
+     *
+     * @var \Magento\Tax\Service\V1\TaxRuleFixtureFactory
+     */
+    private $taxRuleFixtureFactory;
+
+    public function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->taxRuleFixtureFactory = new \Magento\Tax\Service\V1\TaxRuleFixtureFactory();
+    }
+
+    public function tearDown()
+    {
+        $this->tearDownDefaultRules();
+    }
+
+    /**
+     * Tests that the plugin's adjustment config behavior with different tax config.
+     *
+     * @param bool $isTaxIncludeInBasePrice
+     * @param int $priceDisplayType
+     * @param bool $isProductTaxClassIdSet
+     * @dataProvider getTaxConfigData
+     */
+    public function testPrepareAdjustmentConfig($isTaxIncludedInBasePrice, $priceDisplayType, $isProductTaxClassIdSet)
+    {
+        $this->setupDefaultRules();
+
+        $scopeConfig = $this->objectManager->get('Magento\Framework\App\MutableScopeConfig');
+        $scopeConfig->setValue(
+            Config::CONFIG_XML_PATH_PRICE_INCLUDES_TAX,
+            $isTaxIncludedInBasePrice,
+            ScopeInterface::SCOPE_STORE,
+            'default'
+        );
+        $scopeConfig->setValue(
+            Config::CONFIG_XML_PATH_PRICE_DISPLAY_TYPE,
+            $priceDisplayType,
+            ScopeInterface::SCOPE_STORE,
+            'default'
+        );
+
+        $product = $this->objectManager->get('Magento\Catalog\Model\Product')->load(1);
+        if ($isProductTaxClassIdSet) {
+            $product->setTaxClassId($this->taxClasses['DefaultProductClass']);
+        }
+
+        $customerId = 1;
+        $attributePrice = $this->objectManager->create(
+            'Magento\ConfigurableProduct\Pricing\Price\AttributePrice',
+            [
+                'saleableItem' => $product,
+                'quantity' => 1,
+            ]
+        );
+
+        $result = $attributePrice->prepareAdjustmentConfig($customerId);
+        if ($isProductTaxClassIdSet) {
+            $this->assertEquals(7.5, $result['defaultTax']);
+            $this->assertEquals(6.5, $result['currentTax']);
+        } else {
+            $this->assertEquals(0, $result['defaultTax']);
+            $this->assertEquals(0, $result['currentTax']);
+        }
+        $this->assertEquals($isTaxIncludedInBasePrice, $result['includeTax']);
+        $this->assertEquals($priceDisplayType === Config::DISPLAY_TYPE_INCLUDING_TAX, $result['showIncludeTax']);
+        $this->assertEquals($priceDisplayType === Config::DISPLAY_TYPE_BOTH, $result['showBothPrices']);
+        $this->assertEquals($customerId, $result['customerId']);
+    }
+
+    public function getTaxConfigData()
+    {
+        return [
+            'default behavior' => [
+                false,
+                Config::DISPLAY_TYPE_EXCLUDING_TAX,
+                null
+            ],
+            'include tax in base, show include tax in display, no product tax class' => [
+                true,
+                Config::DISPLAY_TYPE_INCLUDING_TAX,
+                null
+            ],
+            'include tax in base, show both include and exclude tax in display, no product tax class' => [
+                true,
+                Config::DISPLAY_TYPE_BOTH,
+                null
+            ],
+            'include tax in base, show both include and exclude tax in display, set product tax class' => [
+                true,
+                Config::DISPLAY_TYPE_BOTH,
+                true
+            ],
+        ];
+    }
+
+    private function setUpDefaultRules()
+    {
+        $this->taxClasses = $this->taxRuleFixtureFactory->createTaxClasses([
+            ['name' => 'DefaultCustomerClass', 'type' => ClassModel::TAX_CLASS_TYPE_CUSTOMER],
+            ['name' => 'DefaultProductClass', 'type' => ClassModel::TAX_CLASS_TYPE_PRODUCT],
+        ]);
+
+        $this->taxRates = $this->taxRuleFixtureFactory->createTaxRates([
+            ['percentage' => 6.5, 'country' => 'US', 'region' => 1],
+            ['percentage' => 7.5, 'country' => 'US', 'region' => 12], // Default store rate
+        ]);
+
+        $this->taxRules = $this->taxRuleFixtureFactory->createTaxRules([
+            [
+                'code' => 'Default Rule',
+                'customer_tax_class_ids' => [$this->taxClasses['DefaultCustomerClass'], 3],
+                'product_tax_class_ids' => [$this->taxClasses['DefaultProductClass']],
+                'tax_rate_ids' => array_values($this->taxRates),
+                'sort_order' => 0,
+                'priority' => 0,
+            ],
+        ]);
+    }
+
+    /**
+     * Helper function that tears down some default rules
+     */
+    private function tearDownDefaultRules()
+    {
+        if ($this->taxRules) {
+            $this->taxRuleFixtureFactory->deleteTaxRules(array_values($this->taxRules));
+        }
+        if ($this->taxRates) {
+            $this->taxRuleFixtureFactory->deleteTaxRates(array_values($this->taxRates));
+        }
+        if ($this->taxClasses) {
+            $this->taxRuleFixtureFactory->deleteTaxClasses(array_values($this->taxClasses));
+        }
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/QuoteDetails/ItemBuilderTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/QuoteDetails/ItemBuilderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7b418c0423847c7e233469ce3942637d7b43167c
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/QuoteDetails/ItemBuilderTest.php
@@ -0,0 +1,213 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1\Data\QuoteDetails;
+
+use Magento\Tax\Service\V1\Data\TaxClassKey;
+
+class ItemBuilderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Object manager
+     *
+     * @var \Magento\Framework\ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * TaxClassKey data object builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\TaxClassKeyBuilder
+     */
+    private $taxClassKeyBuilder;
+
+    /**
+     * Quote Details Item data object builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\QuoteDetails\ItemBuilder
+     */
+    private $quoteDetailsItemBuilder;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->taxClassKeyBuilder = $this->objectManager
+            ->create('Magento\Tax\Service\V1\Data\TaxClassKeyBuilder');
+        $this->quoteDetailsItemBuilder = $this->objectManager
+            ->create('Magento\Tax\Service\V1\Data\QuoteDetails\ItemBuilder');
+    }
+
+    /**
+     * @param array $dataArray Array with data for item
+     * @dataProvider createDataProvider
+     */
+    public function testPopulateWithArray($dataArray)
+    {
+        $itemFromPopulate = $this->quoteDetailsItemBuilder->populateWithArray($dataArray)->create();
+        $itemFromSetters = $this->generateItemWithSetters($dataArray);
+        $this->assertInstanceOf('\Magento\Tax\Service\V1\Data\QuoteDetails\Item', $itemFromPopulate);
+        $this->assertInstanceOf('\Magento\Tax\Service\V1\Data\QuoteDetails\Item', $itemFromSetters);
+        $this->assertEquals($itemFromSetters, $itemFromPopulate);
+        $this->assertEquals($dataArray, $itemFromPopulate->__toArray());
+        $this->assertEquals($dataArray, $itemFromSetters->__toArray());
+    }
+
+    /**
+     * @param array $dataArray Array with data for item
+     * @dataProvider createDataProvider
+     */
+    public function testPopulate($dataArray)
+    {
+        $itemFromSetters = $this->generateItemWithSetters($dataArray);
+        $itemFromPopulate = $this->quoteDetailsItemBuilder->populate($itemFromSetters)->create();
+        $this->assertEquals($itemFromSetters, $itemFromPopulate);
+    }
+
+    public function createDataProvider()
+    {
+        return[
+            'empty' => [[]],
+            'case1' => [$this->getData()['data1']],
+            'case2' => [$this->getData()['data2']],
+        ];
+    }
+
+    public function testMergeDataObjects()
+    {
+        $data = $this->getData();
+        $itemExpected = $this->quoteDetailsItemBuilder->populateWithArray($data['dataMerged'])->create();
+        $itemSomeFields = $this->quoteDetailsItemBuilder->populateWithArray($data['data1'])->create();
+        $itemMoreFields = $this->quoteDetailsItemBuilder->populateWithArray($data['data2'])->create();
+        $itemMerged = $this->quoteDetailsItemBuilder->mergeDataObjects($itemSomeFields, $itemMoreFields);
+        $this->assertEquals($itemExpected->__toArray(), $itemMerged->__toArray());
+    }
+
+    public function testMergeDataObjectsWithArray()
+    {
+        $data = $this->getData();
+        $itemExpected = $this->quoteDetailsItemBuilder->populateWithArray($data['dataMerged'])->create();
+        $itemSomeFields = $this->quoteDetailsItemBuilder->populateWithArray($data['data1'])->create();
+        $itemMerged = $this->quoteDetailsItemBuilder->mergeDataObjectWithArray($itemSomeFields, $data['data2']);
+        $this->assertEquals($itemExpected->__toArray(), $itemMerged->__toArray());
+    }
+
+    /**
+     * Creates a QuoteDetails item data object by calling setters.
+     *
+     * @param array $dataArray
+     * @return Item
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     */
+    private function generateItemWithSetters($dataArray)
+    {
+        $this->quoteDetailsItemBuilder->populateWithArray([]);
+        if (array_key_exists(Item::KEY_CODE, $dataArray)) {
+            $this->quoteDetailsItemBuilder->setCode($dataArray[Item::KEY_CODE]);
+        }
+        if (array_key_exists(Item::KEY_TYPE, $dataArray)) {
+            $this->quoteDetailsItemBuilder->setType($dataArray[Item::KEY_TYPE]);
+        }
+        if (array_key_exists(Item::KEY_TAX_CLASS_KEY, $dataArray)) {
+            $this->quoteDetailsItemBuilder->setTaxClassKey(
+                $this->taxClassKeyBuilder->setType($dataArray[Item::KEY_TAX_CLASS_KEY][TaxClassKey::KEY_TYPE])
+                    ->setValue($dataArray[Item::KEY_TAX_CLASS_KEY][TaxClassKey::KEY_VALUE])
+                    ->create()
+            );
+        }
+        if (array_key_exists(Item::KEY_DISCOUNT_AMOUNT, $dataArray)) {
+            $this->quoteDetailsItemBuilder->setDiscountAmount($dataArray[Item::KEY_DISCOUNT_AMOUNT]);
+        }
+        if (array_key_exists(Item::KEY_QUANTITY, $dataArray)) {
+            $this->quoteDetailsItemBuilder->setQuantity($dataArray[Item::KEY_QUANTITY]);
+        }
+        if (array_key_exists(Item::KEY_PARENT_CODE, $dataArray)) {
+            $this->quoteDetailsItemBuilder->setParentCode($dataArray[Item::KEY_PARENT_CODE]);
+        }
+        if (array_key_exists(Item::KEY_SHORT_DESCRIPTION, $dataArray)) {
+            $this->quoteDetailsItemBuilder->setShortDescription($dataArray[Item::KEY_SHORT_DESCRIPTION]);
+        }
+        if (array_key_exists(Item::KEY_UNIT_PRICE, $dataArray)) {
+            $this->quoteDetailsItemBuilder->setUnitPrice($dataArray[Item::KEY_UNIT_PRICE]);
+        }
+        if (array_key_exists(Item::KEY_TAX_INCLUDED, $dataArray)) {
+            $this->quoteDetailsItemBuilder->setTaxIncluded($dataArray[Item::KEY_TAX_INCLUDED]);
+        }
+        return $this->quoteDetailsItemBuilder->create();
+    }
+
+    /**
+     * Get item data
+     *
+     * @return array
+     */
+    protected function getData()
+    {
+        $data1 = [
+            Item::KEY_CODE => 'item code',
+            Item::KEY_TYPE => 'shipping',
+            Item::KEY_TAX_CLASS_KEY => [
+                TaxClassKey::KEY_TYPE => TaxClassKey::TYPE_ID,
+                TaxClassKey::KEY_VALUE => 1,
+            ],
+            Item::KEY_UNIT_PRICE => 10,
+            Item::KEY_DISCOUNT_AMOUNT => 2.6,
+        ];
+
+        $data2 = [
+            Item::KEY_CODE => 'another code',
+            Item::KEY_TYPE => 'product',
+            Item::KEY_DISCOUNT_AMOUNT => 5,
+            Item::KEY_QUANTITY => 2,
+            Item::KEY_TAX_INCLUDED => false,
+            Item::KEY_SHORT_DESCRIPTION => 'product',
+            Item::KEY_PARENT_CODE => 'parent',
+            Item::KEY_TAX_CLASS_KEY => [
+                TaxClassKey::KEY_TYPE => TaxClassKey::TYPE_NAME,
+                TaxClassKey::KEY_VALUE => 'tax class name',
+            ],
+        ];
+
+        $data = [
+            'data1' => $data1,
+            'data2' => $data2,
+            'dataMerged' => [
+                Item::KEY_CODE => 'another code',
+                Item::KEY_TYPE => 'product',
+                Item::KEY_DISCOUNT_AMOUNT => 5,
+                Item::KEY_QUANTITY => 2,
+                Item::KEY_TAX_INCLUDED => false,
+                Item::KEY_SHORT_DESCRIPTION => 'product',
+                Item::KEY_PARENT_CODE => 'parent',
+                Item::KEY_UNIT_PRICE => 10,
+                Item::KEY_TAX_CLASS_KEY => [
+                    TaxClassKey::KEY_TYPE => TaxClassKey::TYPE_NAME,
+                    TaxClassKey::KEY_VALUE => 'tax class name',
+                ],
+            ]
+        ];
+
+        return $data;
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/QuoteDetailsBuilderTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/QuoteDetailsBuilderTest.php
index d7513b5f4a516c4774ccb6557480f4549933d2d5..10138b0ca3a99a0354da15a5a2ab871e401d7f05 100644
--- a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/QuoteDetailsBuilderTest.php
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/QuoteDetailsBuilderTest.php
@@ -158,10 +158,15 @@ class QuoteDetailsBuilderTest extends \PHPUnit_Framework_TestCase
             ]
         ];
 
+        $taxClassKeyId = [
+            'type' => 'id',
+            'value' => 1,
+        ];
+
         $data = [
             'data1' => [
                 QuoteDetails::KEY_BILLING_ADDRESS => $addressData,
-                QuoteDetails::KEY_CUSTOMER_TAX_CLASS_ID => 1,
+                QuoteDetails::KEY_CUSTOMER_TAX_CLASS_KEY => $taxClassKeyId,
                 QuoteDetails::KEY_CUSTOMER_ID => 1
             ],
             'data2' => [
@@ -171,8 +176,8 @@ class QuoteDetailsBuilderTest extends \PHPUnit_Framework_TestCase
             'dataMerged' => [
                 QuoteDetails::KEY_BILLING_ADDRESS => $addressData,
                 QuoteDetails::KEY_SHIPPING_ADDRESS => $addressData,
-                QuoteDetails::KEY_CUSTOMER_TAX_CLASS_ID => 1,
                 QuoteDetails::KEY_CUSTOMER_ID => 1,
+                QuoteDetails::KEY_CUSTOMER_TAX_CLASS_KEY => $taxClassKeyId,
                 QuoteDetails::KEY_ITEMS => $items
             ]
         ];
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxCalculationServiceTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxCalculationServiceTest.php
index 1638d8bc15b40424b9211e25a5652488513beb26..491a0d9d3f5ac11061cd8ca574b43c8a95aecb62 100644
--- a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxCalculationServiceTest.php
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxCalculationServiceTest.php
@@ -26,6 +26,7 @@ namespace Magento\Tax\Service\V1;
 
 use Magento\Tax\Model\ClassModel;
 use Magento\TestFramework\Helper\Bootstrap;
+use Magento\Tax\Service\V1\Data\TaxClassKey;
 
 /**
  * @magentoDbIsolation enabled
@@ -67,7 +68,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
      *
      * @var int[]
      */
-    private $taxClasses;
+    private $taxClassIds;
 
     /**
      * Array of default tax rates ids.
@@ -137,7 +138,10 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
             'type' => 'product',
             'quantity' => 2,
             'unit_price' => 10,
-            'tax_class_id' => 'DefaultProductClass',
+            'tax_class_key' => [
+                TaxClassKey::KEY_TYPE => TaxClassKey::TYPE_NAME,
+                TaxClassKey::KEY_VALUE => 'DefaultProductClass',
+            ],
         ];
         $oneProductResults = [
             'subtotal' => 20,
@@ -168,6 +172,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 7.5,
                     'discount_tax_compensation_amount' => 0,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 7.5' => [
                             'amount' => 1.5,
@@ -192,7 +197,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
             'type' => 'product',
             'quantity' => 2,
             'unit_price' => 10.75,
-            'tax_class_id' => 'DefaultProductClass',
+            'tax_class_key' => 'DefaultProductClass',
             'tax_included' => true,
         ];
         $oneProductInclTaxResults = $oneProductResults;
@@ -203,7 +208,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
             'type' => 'product',
             'quantity' => 2,
             'unit_price' => 11,
-            'tax_class_id' => 'HigherProductClass',
+            'tax_class_key' => 'HigherProductClass',
             'tax_included' => true,
         ];
         $oneProductInclTaxDiffRateResults = [
@@ -235,6 +240,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 22.0,
                     'discount_tax_compensation_amount' => 0,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 22' => [
                             'amount' => 4.4,
@@ -260,14 +266,14 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                 'type' => 'product',
                 'quantity' => 2,
                 'unit_price' => 10,
-                'tax_class_id' => 'DefaultProductClass',
+                'tax_class_key' => 'DefaultProductClass',
             ],
             [
                 'code' => 'sku_2',
                 'type' => 'product',
                 'quantity' => 20,
                 'unit_price' => 11,
-                'tax_class_id' => 'DefaultProductClass',
+                'tax_class_key' => 'DefaultProductClass',
             ]
         ];
         $twoProductsResults = [
@@ -299,6 +305,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 7.5,
                     'discount_tax_compensation_amount' => 0,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 7.5' => [
                             'amount' => 1.5,
@@ -324,6 +331,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 7.5,
                     'discount_tax_compensation_amount' => 0,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 7.5' => [
                             'amount' => 16.6,
@@ -350,7 +358,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                 'quantity' => 2,
                 'unit_price' => 10.75,
                 'row_total' => 21.5,
-                'tax_class_id' => 'DefaultProductClass',
+                'tax_class_key' => 'DefaultProductClass',
                 'tax_included' => true,
             ],
             [
@@ -359,7 +367,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                 'quantity' => 20,
                 'unit_price' => 11.83,
                 'row_total' => 236.6,
-                'tax_class_id' => 'DefaultProductClass',
+                'tax_class_key' => 'DefaultProductClass',
                 'tax_included' => true,
             ]
         ];
@@ -371,7 +379,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
             'type' => 'product',
             'quantity' => 1,
             'unit_price' => 10,
-            'tax_class_id' => 'DefaultProductClass',
+            'tax_class_key' => 'DefaultProductClass',
             'parent_code' => 'bundle',
         ];
         $bundleProduct['items'][] = [
@@ -379,7 +387,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
             'type' => 'product',
             'quantity' => 2,
             'unit_price' => 0,
-            'tax_class_id' => 'DefaultProductClass',
+            'tax_class_key' => 'DefaultProductClass',
         ];
         $bundleProductResults = [
             'subtotal' => 20,
@@ -410,6 +418,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 7.5,
                     'discount_tax_compensation_amount' => 0,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 7.5' => [
                             'amount' => 1.5,
@@ -510,7 +519,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                         'tax_included' => false,
                     ],
                 ],
-                'customer_tax_class_id' => 'DefaultCustomerClass'
+                'customer_tax_class_key' => 'DefaultCustomerClass'
             ],
             'expected_tax_details' => [
                 'subtotal' => 10.0,
@@ -561,7 +570,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
         ];
 
         $quoteDetailItemWithDefaultProductTaxClass = $prodQuoteDetailItemBase;
-        $quoteDetailItemWithDefaultProductTaxClass['tax_class_id'] = 'DefaultProductClass';
+        $quoteDetailItemWithDefaultProductTaxClass['tax_class_key'] = 'DefaultProductClass';
 
         $prodExpectedItemWithNoProductTaxClass = [
             'code' => [
@@ -574,6 +583,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                 'type' => 'type',
                 'tax_percent' => 0,
                 'discount_tax_compensation_amount' => 0,
+                'associated_item_code' => null,
                 'applied_taxes' => [],
             ],
         ];
@@ -590,6 +600,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                 'type' => 'type',
                 'tax_percent' => 7.5,
                 'discount_tax_compensation_amount' => 0,
+                'associated_item_code' => null,
                 'applied_taxes' => $itemAppliedTaxes,
             ],
         ];
@@ -651,7 +662,10 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                         'tax_included' => true,
                     ],
                 ],
-                'customer_tax_class_id' => 'DefaultCustomerClass'
+                'customer_tax_class_key' => [
+                    TaxClassKey::KEY_TYPE => TaxClassKey::TYPE_NAME,
+                    TaxClassKey::KEY_VALUE => 'DefaultCustomerClass',
+                ],
             ],
             'expected_tax_details' => [
                 'subtotal' => 10.0,
@@ -672,7 +686,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
         ];
 
         $quoteDetailTaxInclItemWithDefaultProductTaxClass = $productTaxInclQuoteDetailItemBase;
-        $quoteDetailTaxInclItemWithDefaultProductTaxClass['tax_class_id'] = 'DefaultProductClass';
+        $quoteDetailTaxInclItemWithDefaultProductTaxClass['tax_class_key'] = 'DefaultProductClass';
 
         $productTaxInclExpectedItemWithNoProductTaxClass = [
             'code' => [
@@ -685,6 +699,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                 'type' => 'type',
                 'tax_percent' => 0,
                 'discount_tax_compensation_amount' => 0,
+                'associated_item_code' => null,
                 'applied_taxes' => [],
             ],
         ];
@@ -715,6 +730,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                 'type' => 'type',
                 'tax_percent' => 7.5,
                 'discount_tax_compensation_amount' => 0,
+                'associated_item_code' => null,
                 'applied_taxes' => [
                     'US - 42 - 7.5' => [
                         'amount' => 0.7,
@@ -795,7 +811,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                         'tax_included' => false,
                     ],
                 ],
-                'customer_tax_class_id' => 'DefaultCustomerClass'
+                'customer_tax_class_key' => 'DefaultCustomerClass'
             ],
             'expected_tax_details' => [
                 'subtotal' => 15.94,
@@ -816,7 +832,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
         ];
 
         $quoteDetailItemWithDefaultProductTaxClass = $prodQuoteDetailItemBase;
-        $quoteDetailItemWithDefaultProductTaxClass['tax_class_id'] = 'DefaultProductClass';
+        $quoteDetailItemWithDefaultProductTaxClass['tax_class_key'] = 'DefaultProductClass';
 
 
         $quoteDetailAppliedTaxesBase = [
@@ -845,6 +861,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                 'type' => 'type',
                 'tax_percent' => 0,
                 'discount_tax_compensation_amount' => 0,
+                'associated_item_code' => null,
                 'applied_taxes' => [],
             ],
         ];
@@ -860,6 +877,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                 'type' => 'type',
                 'tax_percent' => 7.5,
                 'discount_tax_compensation_amount' => 0,
+                'associated_item_code' => null,
                 'applied_taxes' => [
                     'US - 42 - 7.5' => [
                         'amount' => 1.2,
@@ -943,7 +961,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
             'type' => 'product',
             'quantity' => 10,
             'unit_price' => 1,
-            'tax_class_id' => 'DefaultProductClass',
+            'tax_class_key' => 'DefaultProductClass',
         ];
         $oneProductResults = [
             'subtotal' => 10,
@@ -974,6 +992,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 7.5,
                     'discount_tax_compensation_amount' => 0,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 7.5' => [
                             'amount' => 0.75,
@@ -998,7 +1017,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
             'type' => 'product',
             'quantity' => 10,
             'unit_price' => 1.0,
-            'tax_class_id' => 'DefaultProductClass',
+            'tax_class_key' => 'DefaultProductClass',
             'tax_included' => true,
         ];
         $oneProductInclTaxResults = [
@@ -1030,6 +1049,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 7.5,
                     'discount_tax_compensation_amount' => 0,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 7.5' => [
                             'amount' => 0.7,
@@ -1054,7 +1074,10 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
             'type' => 'product',
             'quantity' => 9,
             'unit_price' => 0.33, // this is including the store tax of 10%. Pre tax is 0.3
-            'tax_class_id' => 'HigherProductClass',
+            'tax_class_key' => [
+                TaxClassKey::KEY_TYPE => TaxClassKey::TYPE_NAME,
+                TaxClassKey::KEY_VALUE => 'HigherProductClass',
+            ],
             'tax_included' => true,
         ];
         $oneProductInclTaxDiffRateResults = [
@@ -1086,6 +1109,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 22.0,
                     'discount_tax_compensation_amount' => 0,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 22' => [
                             'amount' => 0.6,
@@ -1111,14 +1135,14 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                 'type' => 'product',
                 'quantity' => 10,
                 'unit_price' => 1,
-                'tax_class_id' => 'DefaultProductClass',
+                'tax_class_key' => 'DefaultProductClass',
             ],
             [
                 'code' => 'sku_2',
                 'type' => 'product',
                 'quantity' => 20,
                 'unit_price' => 11,
-                'tax_class_id' => 'DefaultProductClass',
+                'tax_class_key' => 'DefaultProductClass',
             ]
         ];
         $twoProductsResults = [
@@ -1150,6 +1174,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 7.5,
                     'discount_tax_compensation_amount' => 0,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 7.5' => [
                             'amount' => 0.75,
@@ -1175,6 +1200,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 7.5,
                     'discount_tax_compensation_amount' => 0,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 7.5' => [
                             'amount' => 16.5,
@@ -1200,7 +1226,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                 'type' => 'product',
                 'quantity' => 10,
                 'unit_price' => 0.98,
-                'tax_class_id' => 'DefaultProductClass',
+                'tax_class_key' => 'DefaultProductClass',
                 'tax_included' => true,
             ],
             [
@@ -1208,7 +1234,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                 'type' => 'product',
                 'quantity' => 20,
                 'unit_price' => 11.99,
-                'tax_class_id' => 'DefaultProductClass',
+                'tax_class_key' => 'DefaultProductClass',
                 'tax_included' => true,
             ]
         ];
@@ -1241,6 +1267,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 7.5,
                     'discount_tax_compensation_amount' => 0,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 7.5' => [
                             'amount' => 0.68,
@@ -1266,6 +1293,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 7.5,
                     'discount_tax_compensation_amount' => 0,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 7.5' => [
                             'amount' => 16.73,
@@ -1291,7 +1319,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                 'type' => 'product',
                 'quantity' => 2,
                 'unit_price' => 12.34,
-                'tax_class_id' => 'DefaultProductClass',
+                'tax_class_key' => 'DefaultProductClass',
                 'parent_code' => 'parent_sku',
             ],
             [
@@ -1299,14 +1327,14 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                 'type' => 'product',
                 'quantity' => 10,
                 'unit_price' => 0,
-                'tax_class_id' => 'DefaultProductClass',
+                'tax_class_key' => 'DefaultProductClass',
             ],
             [
                 'code' => 'child_2_sku',
                 'type' => 'product',
                 'quantity' => 2,
                 'unit_price' => 1.99,
-                'tax_class_id' => 'HigherProductClass',
+                'tax_class_key' => 'HigherProductClass',
                 'parent_code' => 'parent_sku',
             ],
         ];
@@ -1351,6 +1379,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 7.5,
                     'discount_tax_compensation_amount' => 0,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 7.5' => [
                             'amount' => 18.51,
@@ -1376,6 +1405,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 22,
                     'discount_tax_compensation_amount' => 0,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 22' => [
                             'amount' => 8.76,
@@ -1446,7 +1476,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
             'type' => 'product',
             'quantity' => 10,
             'unit_price' => 1.89,
-            'tax_class_id' => 'MultipleRulesProductClass',
+            'tax_class_key' => 'MultipleRulesProductClass',
             'tax_included' => true,
             'discount_amount' => 5,
         ];
@@ -1455,7 +1485,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
             'type' => 'product',
             'quantity' => 5,
             'unit_price' => 14.99,
-            'tax_class_id' => 'MultipleRulesProductClass',
+            'tax_class_key' => 'MultipleRulesProductClass',
             'tax_included' => true,
             'discount_amount' => 10,
         ];
@@ -1464,7 +1494,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
             'type' => 'product',
             'quantity' => 1,
             'unit_price' => 99.99,
-            'tax_class_id' => 'MultipleRulesProductClass',
+            'tax_class_key' => 'MultipleRulesProductClass',
             'tax_included' => false,
             'discount_amount' => 5,
         ];
@@ -1526,6 +1556,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 25.7075,
                     'discount_tax_compensation_amount' => 1.03,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 8.25US - 42 - 5 - 55555' => [
                             'amount' => 1.71,
@@ -1568,6 +1599,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 25.7075,
                     'discount_tax_compensation_amount' => 2.05,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 8.25US - 42 - 5 - 55555' => [
                             'amount' => 7.8,
@@ -1610,6 +1642,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                     'type' => 'product',
                     'tax_percent' => 25.7075,
                     'discount_tax_compensation_amount' => 0,
+                    'associated_item_code' => null,
                     'applied_taxes' => [
                         'US - 42 - 8.25US - 42 - 5 - 55555' => [
                             'amount' => 12.59,
@@ -1780,10 +1813,13 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
         array_walk_recursive(
             $data,
             function (&$value, $key) {
-                if ( ($key === 'tax_class_id' || $key === 'customer_tax_class_id')
+                if ( ($key === 'tax_class_key' || $key === 'customer_tax_class_key')
                     && is_string($value)
                 ) {
-                    $value = $this->taxClasses[$value];
+                    $value = [
+                        TaxClassKey::KEY_TYPE => TaxClassKey::TYPE_ID,
+                        TaxClassKey::KEY_VALUE => $this->taxClassIds[$value],
+                    ];
                 }
             }
         );
@@ -1796,7 +1832,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
      */
     private function setUpDefaultRules()
     {
-        $this->taxClasses = $this->taxRuleFixtureFactory->createTaxClasses([
+        $this->taxClassIds = $this->taxRuleFixtureFactory->createTaxClasses([
             ['name' => 'DefaultCustomerClass', 'type' => ClassModel::TAX_CLASS_TYPE_CUSTOMER],
             ['name' => 'DefaultProductClass', 'type' => ClassModel::TAX_CLASS_TYPE_PRODUCT],
             ['name' => 'HigherProductClass', 'type' => ClassModel::TAX_CLASS_TYPE_PRODUCT],
@@ -1829,40 +1865,40 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
         $this->taxRules = $this->taxRuleFixtureFactory->createTaxRules([
             [
                 'code' => 'Default Rule',
-                'customer_tax_class_ids' => [$this->taxClasses['DefaultCustomerClass'], 3],
-                'product_tax_class_ids' => [$this->taxClasses['DefaultProductClass']],
+                'customer_tax_class_ids' => [$this->taxClassIds['DefaultCustomerClass'], 3],
+                'product_tax_class_ids' => [$this->taxClassIds['DefaultProductClass']],
                 'tax_rate_ids' => array_values($this->taxRates),
                 'sort_order' => 0,
                 'priority' => 0,
             ],
             [
                 'code' => 'Higher Rate Rule',
-                'customer_tax_class_ids' => [$this->taxClasses['DefaultCustomerClass'], 3],
-                'product_tax_class_ids' => [$this->taxClasses['HigherProductClass']],
+                'customer_tax_class_ids' => [$this->taxClassIds['DefaultCustomerClass'], 3],
+                'product_tax_class_ids' => [$this->taxClassIds['HigherProductClass']],
                 'tax_rate_ids' => array_values($higherRates),
                 'sort_order' => 0,
                 'priority' => 0,
             ],
             [
                 'code' => 'MultiRule-1',
-                'customer_tax_class_ids' => [$this->taxClasses['DefaultCustomerClass'], 3],
-                'product_tax_class_ids' => [$this->taxClasses['MultipleRulesProductClass']],
+                'customer_tax_class_ids' => [$this->taxClassIds['DefaultCustomerClass'], 3],
+                'product_tax_class_ids' => [$this->taxClassIds['MultipleRulesProductClass']],
                 'tax_rate_ids' => array_values($multiTaxRates1),
                 'sort_order' => 0,
                 'priority' => 0,
             ],
             [
                 'code' => 'MultiRule-2',
-                'customer_tax_class_ids' => [$this->taxClasses['DefaultCustomerClass'], 3],
-                'product_tax_class_ids' => [$this->taxClasses['MultipleRulesProductClass']],
+                'customer_tax_class_ids' => [$this->taxClassIds['DefaultCustomerClass'], 3],
+                'product_tax_class_ids' => [$this->taxClassIds['MultipleRulesProductClass']],
                 'tax_rate_ids' => array_values($multiTaxRatesSamePriority),
                 'sort_order' => 0,
                 'priority' => 0,
             ],
             [
                 'code' => 'MultiRule-3',
-                'customer_tax_class_ids' => [$this->taxClasses['DefaultCustomerClass'], 3],
-                'product_tax_class_ids' => [$this->taxClasses['MultipleRulesProductClass']],
+                'customer_tax_class_ids' => [$this->taxClassIds['DefaultCustomerClass'], 3],
+                'product_tax_class_ids' => [$this->taxClassIds['MultipleRulesProductClass']],
                 'tax_rate_ids' => array_values($multiTaxRatesDifferentPriority),
                 'sort_order' => 0,
                 'priority' => 1,
@@ -1883,7 +1919,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
     {
         $this->taxRuleFixtureFactory->deleteTaxRules(array_values($this->taxRules));
         $this->taxRuleFixtureFactory->deleteTaxRates(array_values($this->taxRates));
-        $this->taxRuleFixtureFactory->deleteTaxClasses(array_values($this->taxClasses));
+        $this->taxRuleFixtureFactory->deleteTaxClasses(array_values($this->taxClassIds));
     }
 
     /**
@@ -1905,7 +1941,7 @@ class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
                 'region' => ['region_id' => 42],
             ],
             'items' => [],
-            'customer_tax_class_id' => 'DefaultCustomerClass',
+            'customer_tax_class_key' => 'DefaultCustomerClass',
         ];
         return $baseQuote;
     }
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxClassServiceTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxClassServiceTest.php
index 594c97b52702793dc106c5d5de02a3498bf7a41f..e693a437546bef80832e120199f4deacac296094 100644
--- a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxClassServiceTest.php
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxClassServiceTest.php
@@ -27,6 +27,7 @@ namespace Magento\Tax\Service\V1;
 use Magento\Framework\Exception\InputException;
 use Magento\Tax\Model\ClassModel as TaxClassModel;
 use Magento\Tax\Service\V1\Data\TaxClassBuilder;
+use Magento\Tax\Service\V1\Data\TaxClassKey;
 use Magento\TestFramework\Helper\Bootstrap;
 
 class TaxClassServiceTest extends \PHPUnit_Framework_TestCase
@@ -254,4 +255,44 @@ class TaxClassServiceTest extends \PHPUnit_Framework_TestCase
 
         $this->taxClassService->updateTaxClass($taxClassId, $taxClassDataObject);
     }
+
+    /**
+     * @magentoDbIsolation enabled
+     */
+    public function testGetTaxClassId()
+    {
+        $taxClassName = 'Get Me';
+        $taxClassDataObject = $this->taxClassBuilder
+            ->setClassName($taxClassName)
+            ->setClassType(TaxClassServiceInterface::TYPE_CUSTOMER)
+            ->create();
+        $taxClassId = $this->taxClassService->createTaxClass($taxClassDataObject);
+        /** @var \Magento\Tax\Service\V1\Data\TaxClassKeyBuilder $taxClassKeyBuilder */
+        $taxClassKeyBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxClassKeyBuilder');
+        $taxClassKeyTypeId = $taxClassKeyBuilder->populateWithArray(
+            [
+                TaxClassKey::KEY_TYPE => TaxClassKey::TYPE_ID,
+                TaxClassKey::KEY_VALUE => $taxClassId,
+            ]
+        )->create();
+        $this->assertEquals(
+            $taxClassId,
+            $this->taxClassService->getTaxClassId($taxClassKeyTypeId, TaxClassServiceInterface::TYPE_CUSTOMER)
+        );
+        $taxClassKeyTypeName = $taxClassKeyBuilder->populateWithArray(
+            [
+                TaxClassKey::KEY_TYPE => TaxClassKey::TYPE_NAME,
+                TaxClassKey::KEY_VALUE => $taxClassName,
+            ]
+        )->create();
+        $this->assertEquals(
+            $taxClassId,
+            $this->taxClassService->getTaxClassId($taxClassKeyTypeId, TaxClassServiceInterface::TYPE_CUSTOMER)
+        );
+        $this->assertNull($this->taxClassService->getTaxClassId(null));
+        $this->assertEquals(
+            null,
+            $this->taxClassService->getTaxClassId($taxClassKeyTypeName, TaxClassServiceInterface::TYPE_PRODUCT)
+        );
+    }
 }
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php
index 77a23de151170a11c92c6f619f9c3cce5db48b68..0331c269cfb163d2631afa28f0c823d36c768a93 100644
--- a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php
@@ -317,11 +317,12 @@ class TaxRateServiceTest extends \PHPUnit_Framework_TestCase
     /**
      * @magentoDbIsolation enabled
      * @expectedException \Magento\Framework\Exception\InputException
-     * @expectedExceptionMessage country_id
+     * @expectedExceptionMessage postcode
      */
     public function testUpdateTaxRateMissingRequiredFields()
     {
         $taxRate = $this->taxRateBuilder
+            ->setCountryId('US')
             ->setRegionId(42)
             ->setPercentageRate(8.25)
             ->setCode('UpdateTaxRates')
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php
index 2e6af1e6a42ec127f97a85a86803889deb620fb7..b3455a2a334e94c2bc236a203e3f60f299e6b1c0 100644
--- a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php
@@ -92,10 +92,18 @@ class TaxRuleServiceTest extends \PHPUnit_Framework_TestCase
      */
     private $taxRules;
 
+    /**
+     * TaxRateService
+     *
+     * @var \Magento\Tax\Service\V1\TaxRateServiceInterface
+     */
+    private $taxRateService;
+
     protected function setUp()
     {
         $this->objectManager = Bootstrap::getObjectManager();
         $this->taxRuleService = $this->objectManager->get('Magento\Tax\Service\V1\TaxRuleServiceInterface');
+        $this->taxRateService = $this->objectManager->get('Magento\Tax\Service\V1\TaxRateServiceInterface');
         $this->taxRuleBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxRuleBuilder');
         $this->taxRuleFixtureFactory = new TaxRuleFixtureFactory();
     }
@@ -339,6 +347,27 @@ class TaxRuleServiceTest extends \PHPUnit_Framework_TestCase
         $this->tearDownDefaultRules();
     }
 
+    /**
+     *
+     * @magentoDbIsolation enabled
+     */
+    public function testGetRatesByCustomerAndProductTaxClassId()
+    {
+        $this->setUpDefaultRules();
+        $taxRateIds = $this->taxRuleService->getTaxRule(current($this->taxRules))->getTaxRateIds();
+        $expectedRates = [];
+        foreach ($taxRateIds as $rateId) {
+            $expectedRates[] = $this->taxRateService->getTaxRate($rateId);
+        }
+        $rates = $this->taxRuleService->getRatesByCustomerAndProductTaxClassId(
+            $this->taxClasses['DefaultCustomerClass'],
+            $this->taxClasses['DefaultProductClass']
+        );
+
+        $this->assertCount(2, $rates);
+        $this->assertEquals($expectedRates, $rates);
+    }
+
     public function searchTaxRulesDataProvider()
     {
         $filterBuilder = Bootstrap::getObjectManager()->create('\Magento\Framework\Service\V1\Data\FilterBuilder');
@@ -349,9 +378,9 @@ class TaxRuleServiceTest extends \PHPUnit_Framework_TestCase
                 null,
                 ['Default Rule']
             ],
-            'sort_order eq 0 AND priority eq 0' => [
+            'customer_tax_class_ids eq 3 AND priority eq 0' => [
                 [
-                    $filterBuilder->setField(TaxRule::SORT_ORDER)->setValue('0')->create(),
+                    $filterBuilder->setField(TaxRule::CUSTOMER_TAX_CLASS_IDS)->setValue(3)->create(),
                     $filterBuilder->setField(TaxRule::PRIORITY)->setValue('0')->create(),
                 ],
                 [],
diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_after_discount_discount_tax.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_after_discount_discount_tax.php
new file mode 100644
index 0000000000000000000000000000000000000000..644fa071b27ade483fdf42f6443334a29dfcfd39
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_after_discount_discount_tax.php
@@ -0,0 +1,143 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+use Magento\Tax\Model\Config;
+use Magento\Tax\Model\Sales\Total\Quote\SetupUtil;
+
+$taxCalculationData['excluding_tax_apply_tax_after_discount_discount_tax'] = [
+    'config_data' => [
+        SetupUtil::CONFIG_OVERRIDES => [
+            Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT => 1,
+            Config::CONFIG_XML_PATH_SHIPPING_TAX_CLASS => SetupUtil::SHIPPING_TAX_CLASS,
+            Config::CONFIG_XML_PATH_DISCOUNT_TAX => 1,
+        ],
+        SetupUtil::TAX_RATE_OVERRIDES => [
+            SetupUtil::TAX_RATE_TX => 20,
+        ],
+        SetupUtil::TAX_RULE_OVERRIDES => [
+            [
+                //tax rule for product
+                'code' => 'Product Tax Rule',
+                'tax_product_class' => [SetupUtil::PRODUCT_TAX_CLASS_1],
+            ],
+            [
+                //tax rule for shipping
+                'code' => 'Shipping Tax Rule',
+                'tax_product_class' => [SetupUtil::SHIPPING_TAX_CLASS],
+                'tax_rate' => [SetupUtil::TAX_RATE_SHIPPING],
+            ],
+        ],
+    ],
+    'quote_data' => [
+        'billing_address' => [
+            'region_id' => SetupUtil::REGION_TX,
+        ],
+        'shipping_address' => [
+            'region_id' => SetupUtil::REGION_TX,
+        ],
+        'items' => [
+            [
+                'sku' => 'simple1',
+                'price' => 10,
+                'qty' => 2,
+            ],
+        ],
+        'shipping_method' => 'flatrate_flatrate',
+        'shopping_cart_rules' => [
+            [
+                'discount_amount' => 50,
+            ],
+        ],
+    ],
+    'expected_results' => [
+        'address_data' => [
+            'subtotal' => 20,
+            'base_subtotal' => 20,
+            'subtotal_incl_tax' => 24,
+            'base_subtotal_incl_tax' => 24,
+            'tax_amount' => 2.35,
+            'base_tax_amount' => 2.35,
+            'shipping_amount' => 10,
+            'base_shipping_amount' => 10,
+            'shipping_incl_tax' => 10.75,
+            'base_shipping_incl_tax' => 10.75,
+            'shipping_tax_amount' => 0.75,
+            'base_shipping_tax_amount' => 0.75,
+            'discount_amount' => -12,
+            'base_discount_amount' => -12,
+            'hidden_tax_amount' => 0,
+            'base_hidden_tax_amount' => 0,
+            'shipping_hidden_tax_amount' => 0,
+            'base_shipping_hidden_tax_amount' => 0,
+            'grand_total' => 20.35,
+            'base_grand_total' => 20.35,
+            'applied_taxes' => [
+                SetupUtil::TAX_RATE_TX => [
+                    'percent' => 20,
+                    'amount' => 1.6,
+                    'base_amount' => 1.6,
+                    'rates' => [
+                        [
+                            'code' => SetupUtil::TAX_RATE_TX,
+                            'title' => SetupUtil::TAX_RATE_TX,
+                            'percent' => 20,
+                        ],
+                    ],
+                ],
+                SetupUtil::TAX_RATE_SHIPPING => [
+                    'percent' => 7.5,
+                    'amount' => 0.75,
+                    'base_amount' => 0.75,
+                    'rates' => [
+                        [
+                            'code' => SetupUtil::TAX_RATE_SHIPPING,
+                            'title' => SetupUtil::TAX_RATE_SHIPPING,
+                            'percent' => 7.5,
+                        ],
+                    ],
+                ],
+            ],
+        ],
+        'items_data' => [
+            'simple1' => [
+                'row_total' => 20,
+                'base_row_total' => 20,
+                'tax_percent' => 20,
+                'price' => 10,
+                'base_price' => 10,
+                'price_incl_tax' => 12,
+                'base_price_incl_tax' => 12,
+                'row_total_incl_tax' => 24,
+                'base_row_total_incl_tax' => 24,
+                'tax_amount' => 1.6,
+                'base_tax_amount' => 1.6,
+                'discount_amount' => 12,
+                'base_discount_amount' => 12,
+                'discount_percent' => 50,
+                'hidden_tax_amount' => 0,
+                'base_hidden_tax_amount' => 0,
+            ],
+        ],
+    ],
+];
\ No newline at end of file
diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_row.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_row.php
index 8b18adbb1126af1f46c2028d6ea721c80cbb952a..82435beca6d279a651d35c853d32bec9cd39b42a 100644
--- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_row.php
+++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_row.php
@@ -162,6 +162,9 @@ $taxCalculationData['multi_tax_rule_two_row_calculate_subtotal_yes_row'] = [
                                 'title' => SetupUtil::TAX_RATE_TX,
                             ],
                         ],
+                        'item_id' => null,
+                        'item_type' => 'product',
+                        'associated_item_id' => null,
                     ],
                     [
                         'amount' => 0.5,
@@ -175,6 +178,9 @@ $taxCalculationData['multi_tax_rule_two_row_calculate_subtotal_yes_row'] = [
                                 'title' => SetupUtil::TAX_RATE_AUSTIN,
                             ],
                         ],
+                        'item_id' => null,
+                        'item_type' => 'product',
+                        'associated_item_id' => null,
                     ],
                 ],
             ],
@@ -208,6 +214,9 @@ $taxCalculationData['multi_tax_rule_two_row_calculate_subtotal_yes_row'] = [
                                 'title' => SetupUtil::TAX_RATE_TX,
                             ],
                         ],
+                        'item_id' => null,
+                        'item_type' => 'product',
+                        'associated_item_id' => null,
                     ],
                     [
                         'amount' => 0.52,
@@ -221,6 +230,9 @@ $taxCalculationData['multi_tax_rule_two_row_calculate_subtotal_yes_row'] = [
                                 'title' => SetupUtil::TAX_RATE_AUSTIN,
                             ],
                         ],
+                        'item_id' => null,
+                        'item_type' => 'product',
+                        'associated_item_id' => null,
                     ],
                 ],
             ],
diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_total.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_total.php
index d0d85808d2cd888e87bbd9131ba0a8252c7478ba..8586e95a4e6c91a50407f11a369c3550cd9e5861 100644
--- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_total.php
+++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_total.php
@@ -162,6 +162,9 @@ $taxCalculationData['multi_tax_rule_two_row_calculate_subtotal_yes_total'] = [
                                 'title' => SetupUtil::TAX_RATE_TX,
                             ],
                         ],
+                        'item_id' => null,
+                        'item_type' => 'product',
+                        'associated_item_id' => null,
                     ],
                     [
                         'amount' => 0.5,
@@ -175,6 +178,9 @@ $taxCalculationData['multi_tax_rule_two_row_calculate_subtotal_yes_total'] = [
                                 'percent' => 5,
                             ],
                         ],
+                        'item_id' => null,
+                        'item_type' => 'product',
+                        'associated_item_id' => null,
                     ],
                 ],
             ],
@@ -208,6 +214,9 @@ $taxCalculationData['multi_tax_rule_two_row_calculate_subtotal_yes_total'] = [
                                 'title' => SetupUtil::TAX_RATE_TX,
                             ],
                         ],
+                        'item_id' => null,
+                        'item_type' => 'product',
+                        'associated_item_id' => null,
                     ],
                     [
                         'amount' => 0.53,
@@ -221,6 +230,9 @@ $taxCalculationData['multi_tax_rule_two_row_calculate_subtotal_yes_total'] = [
                                 'title' => SetupUtil::TAX_RATE_AUSTIN,
                             ],
                         ],
+                        'item_id' => null,
+                        'item_type' => 'product',
+                        'associated_item_id' => null,
                     ],
                 ],
             ],
diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php b/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php
index 452752b9baaf076c3abfdcd39e6b2a6ec74a00fb..080fefd9f6f052abfd8ac6c3656cd6f173fbca1d 100644
--- a/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php
+++ b/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php
@@ -30,6 +30,7 @@
 $taxCalculationData = [];
 
 require_once __DIR__ . '/scenarios/excluding_tax_apply_tax_after_discount.php';
+require_once __DIR__ . '/scenarios/excluding_tax_apply_tax_after_discount_discount_tax.php';
 require_once __DIR__ . '/scenarios/excluding_tax_apply_tax_before_discount.php';
 require_once __DIR__ . '/scenarios/excluding_tax_unit.php';
 require_once __DIR__ . '/scenarios/excluding_tax_row.php';
diff --git a/dev/tests/integration/testsuite/Magento/Test/Integrity/LayoutTest.php b/dev/tests/integration/testsuite/Magento/Test/Integrity/LayoutTest.php
index cc97ae4ea17c41f14170f3b07653332a3adbdd27..1feef2c21fa6c920612ba11fc38ceb970f669407 100644
--- a/dev/tests/integration/testsuite/Magento/Test/Integrity/LayoutTest.php
+++ b/dev/tests/integration/testsuite/Magento/Test/Integrity/LayoutTest.php
@@ -76,9 +76,6 @@ class LayoutTest extends \PHPUnit_Framework_TestCase
         if ($refName) {
             $refNode = $xml->xpath("/layouts/{$refName}");
             if (!$refNode) {
-                if ($refName == 'checkout_cart_configure' || $refName == 'checkout_cart_configurefailed') {
-                    $this->markTestIncomplete('MAGETWO-9182');
-                }
                 $errors[$name][] = "Node '{$refName}', referenced in hierarchy, does not exist";
             }
         }
diff --git a/dev/tests/integration/testsuite/Magento/Test/Integrity/Theme/TemplateFilesTest.php b/dev/tests/integration/testsuite/Magento/Test/Integrity/Theme/TemplateFilesTest.php
index 7f27f901c9a36d2b074c47f7029d6fd7d2571655..27d7874280831f076976085d69074f15c991052c 100644
--- a/dev/tests/integration/testsuite/Magento/Test/Integrity/Theme/TemplateFilesTest.php
+++ b/dev/tests/integration/testsuite/Magento/Test/Integrity/Theme/TemplateFilesTest.php
@@ -33,19 +33,6 @@ class TemplateFilesTest extends \Magento\TestFramework\TestCase\AbstractIntegrit
         $invalidTemplates = array();
         foreach ($this->templatesDataProvider() as $template) {
             list($area, $themeId, $module, $file, $xml) = $template;
-
-            if ($area === 'frontend' && in_array(
-                $module . '::' . $file,
-                array(
-                    'Magento_Reports::Magento_Catalog::product/list/items.phtml',
-                    'Magento_Review::redirect.phtml',
-                    'Magento_Theme::blank.phtml'
-                )
-            )
-            ) {
-                continue; // $this->markTestIncomplete('MAGETWO-9806');
-            }
-
             $params = array('area' => $area, 'themeId' => $themeId, 'module' => $module);
             try {
                 $templateFilename = \Magento\TestFramework\Helper\Bootstrap::getObjectmanager()
diff --git a/dev/tests/integration/testsuite/Magento/Weee/Model/ObserverTest.php b/dev/tests/integration/testsuite/Magento/Weee/Model/ObserverTest.php
index 2a1b20179716bf7665996d22748e794292c1404d..0521f1e57be97ca6276323054120b05cf00f23aa 100644
--- a/dev/tests/integration/testsuite/Magento/Weee/Model/ObserverTest.php
+++ b/dev/tests/integration/testsuite/Magento/Weee/Model/ObserverTest.php
@@ -59,7 +59,7 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
             \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
                 'Magento\Framework\App\Config\MutableScopeConfigInterface'
             )->setValue(
-                'tax/weee/display',
+                Config::XML_PATH_FPT_DISPLAY_PRODUCT_VIEW,
                 $mode,
                 \Magento\Store\Model\ScopeInterface::SCOPE_STORE
             );
@@ -78,7 +78,7 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
             \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
                 'Magento\Framework\App\Config\MutableScopeConfigInterface'
             )->setValue(
-                'tax/weee/display',
+                Config::XML_PATH_FPT_DISPLAY_PRODUCT_VIEW,
                 $mode,
                 \Magento\Store\Model\ScopeInterface::SCOPE_STORE
             );
diff --git a/dev/tests/js/testsuite/mage/form/form-test.js b/dev/tests/js/testsuite/mage/form/form-test.js
index 328586b50badac5afaf562b0676f2e5aaecbef77..df04f03911ea951b37d4f547caa2414034106dc2 100644
--- a/dev/tests/js/testsuite/mage/form/form-test.js
+++ b/dev/tests/js/testsuite/mage/form/form-test.js
@@ -69,9 +69,9 @@ FormTest.prototype.testGetHandlers = function() {
 FormTest.prototype.testStoreAttribute = function() {
     var form = jQuery('#form').form(),
         initialFormAttrs = {
-            action: form.prop('action'),
-            target: form.prop('target'),
-            method: form.prop('method')
+            action: form.attr('action'),
+            target: form.attr('target'),
+            method: form.attr('method')
         };
     form.data("form")._storeAttribute('action');
     form.data("form")._storeAttribute('target');
@@ -100,7 +100,7 @@ FormTest.prototype.testBind = function() {
 };
 FormTest.prototype.testGetActionUrl = function() {
     var form = jQuery('#form').form(),
-        action = form.prop('action'),
+        action = form.attr('action'),
         testUrl = 'new/action/url',
         testArgs = {
             args: {arg: 'value'}
@@ -114,9 +114,9 @@ FormTest.prototype.testGetActionUrl = function() {
 FormTest.prototype.testProcessData = function() {
     var form = jQuery('#form').form(),
         initialFormAttrs = {
-            action: form.prop('action'),
-            target: form.prop('target'),
-            method: form.prop('method')
+            action: form.attr('action'),
+            target: form.attr('target'),
+            method: form.attr('method')
         },
         testSimpleData = {
             action: 'new/action/url',
@@ -224,9 +224,9 @@ FormTest.prototype.testSubmit = function() {
 
     form.data("form")._submit({type: 'save'});
 
-    assertEquals(form.prop('action'), form.data("form").oldAttributes.action);
-    assertEquals(form.prop('target'), form.data("form").oldAttributes.target);
-    assertEquals(form.prop('method'), form.data("form").oldAttributes.method);
+    assertEquals(form.attr('action'), form.data("form").oldAttributes.action);
+    assertEquals(form.attr('target'), form.data("form").oldAttributes.target);
+    assertEquals(form.attr('method'), form.data("form").oldAttributes.method);
     assertTrue(formSubmitted);
     form.off('submit');
 };
diff --git a/dev/tests/js/testsuite/mage/validation/test-validation.js b/dev/tests/js/testsuite/mage/validation/test-validation.js
index 5f3258896db7e224c06e266fd745ed91c60b6b32..2bde1bc8126fd2be55a2a0a41833879a58088bcf 100644
--- a/dev/tests/js/testsuite/mage/validation/test-validation.js
+++ b/dev/tests/js/testsuite/mage/validation/test-validation.js
@@ -219,14 +219,14 @@ test( "testValidateSsn", function() {
 
 test( "testValidateZip", function() {
     expect(8);
-    equal(true, $.validator.methods['validate-zip'].call(this, ""));
-    equal(true, $.validator.methods['validate-zip'].call(this, null));
-    equal(true, $.validator.methods['validate-zip'].call(this, undefined));
-    equal(false, $.validator.methods['validate-zip'].call(this, "   "));
-    equal(true, $.validator.methods['validate-zip'].call(this, "12345-1234"));
-    equal(true, $.validator.methods['validate-zip'].call(this, "02345"));
-    equal(false, $.validator.methods['validate-zip'].call(this, "1234"));
-    equal(false, $.validator.methods['validate-zip'].call(this, "1234-1234"));
+    equal(true, $.validator.methods['validate-zip-us'].call(this, ""));
+    equal(true, $.validator.methods['validate-zip-us'].call(this, null));
+    equal(true, $.validator.methods['validate-zip-us'].call(this, undefined));
+    equal(false, $.validator.methods['validate-zip-us'].call(this, "   "));
+    equal(true, $.validator.methods['validate-zip-us'].call(this, "12345-1234"));
+    equal(true, $.validator.methods['validate-zip-us'].call(this, "02345"));
+    equal(false, $.validator.methods['validate-zip-us'].call(this, "1234"));
+    equal(false, $.validator.methods['validate-zip-us'].call(this, "1234-1234"));
 });
 
 test( "testValidateDateAu", function() {
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/CircularDependencyTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/CircularDependencyTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7386046e7bd573cbe1361ca9e907dacc8c34b1e2
--- /dev/null
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/CircularDependencyTest.php
@@ -0,0 +1,90 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Test\Integrity\App\Language;
+
+use \Magento\Framework\App\Language\Config;
+
+class CircularDependencyTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Config[][]
+     */
+    private $packs;
+
+    /**
+     * Test circular dependencies between languages
+     */
+    public function testCircularDependencies()
+    {
+        $package = new Package();
+        $rootDirectory = \Magento\TestFramework\Utility\Files::init()->getPathToSource();
+        $declaredLanguages = $package->readDeclarationFiles($rootDirectory);
+        $packs = [];
+        foreach ($declaredLanguages as $language) {
+            $filePath = reset($language);
+            $languageConfig = new Config(file_get_contents($filePath));
+            $this->packs[$languageConfig->getVendor()][$languageConfig->getPackage()] = $languageConfig;
+            $packs[] = $languageConfig;
+        }
+
+        /** @var $languageConfig Config */
+        foreach ($packs as $languageConfig) {
+            $languages = [];
+            /** @var $config Config */
+            foreach ($this->collectCircularInheritance($languageConfig) as $config) {
+                $languages[] = $config->getVendor() . '/' . $config->getPackage();
+            }
+            if (!empty($languages)) {
+                $this->fail("Circular dependency detected:\n" . implode(' -> ', $languages));
+            }
+        }
+    }
+
+    /**
+     * @param Config $languageConfig
+     * @param array $languageList
+     * @param bool $isCircular
+     * @return array|null
+     */
+    private function collectCircularInheritance(Config $languageConfig, &$languageList = [], &$isCircular = false)
+    {
+        $packKey = implode('|', [$languageConfig->getVendor(), $languageConfig->getPackage()]);
+        if (isset($languageList[$packKey])) {
+            $isCircular = true;
+        } else {
+            $languageList[$packKey] = $languageConfig;
+            foreach ($languageConfig->getUses() as $reuse) {
+                if (isset($this->packs[$reuse['vendor']][$reuse['package']])) {
+                    $this->collectCircularInheritance(
+                        $this->packs[$reuse['vendor']][$reuse['package']],
+                        $languageList,
+                        $isCircular
+                    );
+                }
+            }
+        }
+        return $isCircular ? $languageList : [];
+    }
+}
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/ConfigTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/ConfigTest.php
index f36bad617a18d2b44a2f8f6e5fe17e2e106a0efc..2576b0e265bf052ec64e36551ade9e7bea2e435a 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/ConfigTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/ConfigTest.php
@@ -31,9 +31,9 @@ class ConfigTest extends \Magento\TestFramework\Integrity\AbstractConfig
         $expectedErrors = array(
             "Element 'code': [facet 'pattern'] The value 'e_GB' is not accepted by the pattern",
             "Element 'code': 'e_GB' is not a valid value of the atomic type 'codeType'",
-            "Element 'vendor': [facet 'pattern'] The value 'agento' is not accepted by the pattern",
-            "Element 'vendor': 'agento' is not a valid value of the atomic type",
-            "Element 'sort_odrer': This element is not expected. Expected is one of",
+            "Element 'vendor': [facet 'pattern'] The value 'Magento' is not accepted by the pattern",
+            "Element 'vendor': 'Magento' is not a valid value of the atomic type",
+            "Element 'sort_odrer': This element is not expected. Expected is",
         );
         parent::testSchemaUsingInvalidXml($expectedErrors);
     }
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/PackageTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/PackageTest.php
index 4ff37b870bb5cad5dfdf1b6aea69fe2e146dbf00..181254ab9fcee7d62ec49bce83faa7a1188113ec 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/PackageTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/PackageTest.php
@@ -32,16 +32,14 @@ class PackageTest extends \PHPUnit_Framework_TestCase
     /**
      * @param string $file
      * @param string $expectedVendor
-     * @param string $expectedCode
+     * @param string $expectedPackage
      * @dataProvider declaredConsistentlyDataProvider
      */
-    public function testDeclaredConsistently($file, $expectedVendor, $expectedCode)
+    public function testDeclaredConsistently($file, $expectedVendor, $expectedPackage)
     {
-        $dom = new \DOMDocument();
-        $dom->load($file);
-        $root = $dom->documentElement;
-        \Magento\Framework\App\Language\Dictionary::assertVendor($expectedVendor, $root);
-        \Magento\Framework\App\Language\Dictionary::assertCode($expectedCode, $root);
+        $languageConfig = new \Magento\Framework\App\Language\Config(file_get_contents($file));
+        $this->assertEquals($expectedVendor, $languageConfig->getVendor());
+        $this->assertEquals($expectedPackage, $languageConfig->getPackage());
     }
 
     /**
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/TranslationFiles.php b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/TranslationFiles.php
index c58642f9063300dd739414e9fc22891f3c73e2c6..bf3b5085d43ae5af24043713e9c569dfb861a9a8 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/TranslationFiles.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/TranslationFiles.php
@@ -96,13 +96,13 @@ class TranslationFiles extends \PHPUnit_Framework_TestCase
      */
     protected function printMessage($failures, $message = '')
     {
-        $message .= "\n";
+        $message .= PHP_EOL;
         foreach ($failures as $locale => $localeErrors) {
-            $message .= $locale . "\n";
+            $message .= $locale . PHP_EOL;
             foreach ($localeErrors as $typeError => $error) {
-                $message .= "\t" . $typeError . "\n";
+                $message .= PHP_EOL . "##########" . PHP_EOL . ucfirst($typeError) . ':' . PHP_EOL;
                 foreach ($error as $phrase) {
-                    $message .= "\t\t" . $phrase . "\n";
+                    $message .= '"' . $phrase . '","' . $phrase . '"' . PHP_EOL;
                 }
             }
         }
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_invalid.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_invalid.xml
index 9366bbeedcfb54c7dbe17db6dfe31e89ac5b29bd..e86fff00763647c3fed796cebf0770fbfec9bf87 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_invalid.xml
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_invalid.xml
@@ -25,7 +25,7 @@
 -->
 <language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
     <code>e_GB</code>
-    <vendor>agento</vendor>
+    <vendor>Magento</vendor>
     <sort_odrer>100</sort_odrer>
     <use code="en_GB"/>
 </language>
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_valid.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_valid.xml
index d13de1dd866bcdc5a9bbb387c573ce1a62d83a2e..04363d89ad421db85a8dfd8d82456cdda23ddea8 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_valid.xml
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_valid.xml
@@ -25,7 +25,9 @@
 -->
 <language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
     <code>en_GB</code>
-    <vendor>Magento</vendor>
+    <vendor>magento</vendor>
+    <package>en_gb</package>
     <sort_order>100</sort_order>
-    <use vendor="OxfordUniversity" code="en_GB"/>
+    <use vendor="oxford-university" package="en_us"/>
+    <use vendor="oxford-university" package="en_gb"/>
 </language>
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php
index 7f0b60616a16406524001ce631432b4b7894ed09..0feded3cb23129449e1a33130bc04d6257c4d8fa 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php
@@ -665,8 +665,7 @@ return array(
         '\Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super\Config\Matrix'
     ),
     array(
-        'Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Super\Config\Simple',
-        'Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super\Config\Simple'
+        'Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Super\Config\Simple'
     ),
     array(
         'Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Super\Config',
@@ -1376,6 +1375,7 @@ return array(
     array('Magento\Framework\HTTP\HandlerInterface'),
     array('Magento\Backend\Model\Request\PathInfoProcessor'),
     array('Magento\Backend\Model\Router\NoRouteHandler'),
+    array('Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super\Config\Simple'),
     array('Magento\Core\Model\Request\PathInfoProcessor', 'Magento\Store\App\Request\PathInfoProcessor'),
     array('Magento\Core\Model\Request\RewriteService'),
     array('Magento\Core\Model\Router\NoRouteHandler'),
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
index dc21a5b7b0b5f209cf15b32521e312d2168e988a..fd30dd301cd457ed4f7bc6b01dd28f59aa465aeb 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
@@ -389,6 +389,7 @@ return array(
     array('getAllOrderEntityIds', 'Magento\Rss\Model\Resource\Order'),
     array('getAllOrderEntityTypeIds', 'Magento\Rss\Model\Resource\Order'),
     array('getAnonSuffix'),
+    ['getAttributesById', 'Magento\Eav\Model\Entity\AbstractEntity'],
     array('getAttributeDataModelFactory', 'Magento\Eav\Model\Validator\Attribute\Data'),
     array('getAttributes', 'Magento\Customer\Helper\Address'),
     array('getAttributesJson', 'Magento\Backend\Block\Catalog\Product\Edit\Tab\Super\Config', 'getAttributes'),
@@ -1792,6 +1793,14 @@ return array(
     ['reset', 'Magento\CatalogInventory\Model\Stock\Item'],
     ['prepareValueForDuplicate', 'Magento\Catalog\Model\Product\Option\Value'],
     ['prepareOptionForDuplicate', '\Magento\Catalog\Model\Product\Option'],
+    [
+        'getFlatColums',
+        'Magento\Eav\Model\Entity\Attribute\Source\AbstractSource',
+        'Magento\Eav\Model\Entity\Attribute\Source\AbstractSource::getFlatColumns'
+    ],
     ['addProductAdvanced', '\Magento\Sales\Model\Quote'],
     ['translateArray', 'Magento\Framework\App\Helper\AbstractHelper'],
+    ['getCalculator', '\Magento\Tax\Helper\Data'],
+    ['getRatesForAllProductTaxClasses', 'Magento\Tax\Model\Calculation'],
+    ['getRatesForAllCustomerTaxClasses', 'Magento\Tax\Model\Calculation']
 );
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php
index 330062a24478d82b30a63b1d519ec87f1d07acff..fa620e572b00cde146d396d7214341701197ea25 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php
@@ -340,4 +340,8 @@ return array(
     ['_productInstance', 'Magento\CatalogInventory\Model\Stock\Item'],
     ['_regionBuilder', 'Magento\Customer\Model\Address\Converter'],
     ['_scopeConfig', 'Magento\CatalogInventory\Helper\Minsaleqty', 'scopeConfig'],
+    ['_stopFurtherRules', 'Magento\SalesRule\Model\Validator'],
+    ['_usageFactory', 'Magento\SalesRule\Model\Validator', 'Magento\SalesRule\Model\Validator\Utility'],
+    ['_couponFactory', 'Magento\SalesRule\Model\Validator', 'Magento\SalesRule\Model\Validator\Utility'],
+    ['_customerFactory', 'Magento\SalesRule\Model\Validator', 'Magento\SalesRule\Model\Validator\Utility'],
 );
diff --git a/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php b/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php
index 7099d66c0369a230c53d049b9ca8693fb750fc7f..273663ecf30ef6c605044db1ec56f74c28190410 100644
--- a/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php
@@ -141,7 +141,6 @@ class LiveCodeTest extends PHPUnit_Framework_TestCase
     public function testAnnotationStandard()
     {
         $reportFile = self::$reportDir . '/phpcs_annotations_report.xml';
-        $warningSeverity = 5;
         $wrapper = new Wrapper();
         $codeSniffer = new CodeSniffer(
             realpath(__DIR__ . '/../../../../framework/Magento/ruleset.xml'),
@@ -152,14 +151,11 @@ class LiveCodeTest extends PHPUnit_Framework_TestCase
             $this->markTestSkipped('PHP Code Sniffer is not installed.');
         }
         self::setupFileLists('phpcs');
-        // Scan for error amount
-        $result = $codeSniffer->run(self::$whiteList, self::$blackList, array('php'), 0);
-        // Rescan to generate report with warnings.
-        $codeSniffer->run(self::$whiteList, self::$blackList, array('php'), $warningSeverity);
-        // Fail if there are errors in report.
+
+        $severity = 0; // Change to 5 to see the warnings
         $this->assertEquals(
             0,
-            $result,
+            $result = $codeSniffer->run(self::$whiteList, self::$blackList, array('php'), $severity),
             "PHP Code Sniffer has found {$result} error(s): See detailed report in {$reportFile}"
         );
     }
diff --git a/dev/tests/static/testsuite/Magento/Test/Php/_files/blacklist/common.txt b/dev/tests/static/testsuite/Magento/Test/Php/_files/blacklist/common.txt
index f9f4ce6856d861ab56e36b7485d0142190b534c2..54ea92a6e2f4ebd8ba0705310f5cc131498a7c44 100644
--- a/dev/tests/static/testsuite/Magento/Test/Php/_files/blacklist/common.txt
+++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/blacklist/common.txt
@@ -16,6 +16,7 @@ app/code/Magento/User/view
 app/code/Magento/Webapi/view
 app/code/Magento/GroupedProduct/view
 app/code/Magento/RecurringPayment/view
+app/code/Magento/UrlRedirect/view
 dev/tests/integration/framework/Magento/TestFramework/Db/Mysql.php
 dev/tests/integration/framework/Magento/TestFramework/Db/Adapter/Mysql.php
 dev/tests/integration/framework/Magento/TestFramework/Db/ConnectionAdapter.php
diff --git a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt
index 40be27df10932f32ce172b37712ad69222e70e87..f33297f898b91182cb7fa2300d6470bdcd75ca25 100644
--- a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt
+++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt
@@ -1,4 +1,3 @@
-Find/Feed/Block/Adminhtml
 Magento/Adminhtml
 Magento/Authorizenet/Model
 Magento/Backend
@@ -126,3 +125,4 @@ Magento/Usps/Model/Carrier
 Magento/Dhl/Model
 Magento/Shipping/Model
 Magento/Catalog/Service/V1/Category
+Magento/UrlRedirect/Model
diff --git a/dev/tests/static/testsuite/Magento/Test/Php/_files/whitelist/common.txt b/dev/tests/static/testsuite/Magento/Test/Php/_files/whitelist/common.txt
index e97a5303a151b1fb35b38c6732421ef546026492..63ed5b003a15bf6696db75fb448d89c7c40d94d4 100644
--- a/dev/tests/static/testsuite/Magento/Test/Php/_files/whitelist/common.txt
+++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/whitelist/common.txt
@@ -116,6 +116,7 @@ app/code/Magento/Shipping/Model/Resource/Order
 app/code/Magento/Theme
 app/code/Magento/Webapi
 app/code/Magento/GroupedProduct
+app/code/Magento/UrlRedirect
 app/code/Magento/Wishlist/Block/Link.php
 dev/shell
 dev/tests/functional
diff --git a/dev/tests/unit/filename b/dev/tests/unit/filename
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/dev/tests/unit/filename.csv b/dev/tests/unit/filename.csv
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/dev/tests/unit/filename.invalid_type b/dev/tests/unit/filename.invalid_type
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/dev/tests/unit/framework/Magento/TestFramework/Helper/ObjectManager.php b/dev/tests/unit/framework/Magento/TestFramework/Helper/ObjectManager.php
index 36507e50baeeb2dccabb6f44628e57c3fc42706b..5a2ff33df0f2e597add3c6b5aaccd48aabc5272f 100644
--- a/dev/tests/unit/framework/Magento/TestFramework/Helper/ObjectManager.php
+++ b/dev/tests/unit/framework/Magento/TestFramework/Helper/ObjectManager.php
@@ -198,6 +198,12 @@ class ObjectManager
         $reflectionClass = new \ReflectionClass($className);
         $builderObject = $reflectionClass->newInstanceArgs($constructArguments);
 
+        $objectFactory->expects($this->_testObject->any())
+            ->method('populateWithArray')
+            ->will($this->_testObject->returnSelf());
+        $objectFactory->expects($this->_testObject->any())
+            ->method('populate')
+            ->will($this->_testObject->returnSelf());
         $objectFactory->expects($this->_testObject->any())
             ->method('create')
             ->will($this->_testObject->returnCallback(
@@ -243,7 +249,7 @@ class ObjectManager
                 if ($parameter->getClass()) {
                     $argClassName = $parameter->getClass()->getName();
                 }
-                $object = $this->_createArgumentMock($argClassName, $arguments);
+                $object = $this->_getMockObject($argClassName, $arguments);
             } catch (\ReflectionException $e) {
                 $parameterString = $parameter->__toString();
                 $firstPosition = strpos($parameterString, '<required>');
@@ -285,4 +291,24 @@ class ObjectManager
         );
         return $mock;
     }
+
+    /**
+     * Helper function that creates a mock object for a given class name.
+     *
+     * Will return a real object in some cases to assist in testing.
+     *
+     * @param string $argClassName
+     * @param array $arguments
+     * @return null|object|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private function _getMockObject($argClassName, array $arguments)
+    {
+        if (is_subclass_of($argClassName, '\Magento\Framework\Service\Data\AbstractObjectBuilder')) {
+            $object = $this->getBuilder($argClassName, $arguments);
+            return $object;
+        } else {
+            $object = $this->_createArgumentMock($argClassName, $arguments);
+            return $object;
+        }
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Backend/Controller/Adminhtml/System/Config/SaveTest.php b/dev/tests/unit/testsuite/Magento/Backend/Controller/Adminhtml/System/Config/SaveTest.php
index fd073c45107cd59530c9c4caa473fbf17585fdfd..33960d51babc74deeadb6feed37147d3eabe4e91 100644
--- a/dev/tests/unit/testsuite/Magento/Backend/Controller/Adminhtml/System/Config/SaveTest.php
+++ b/dev/tests/unit/testsuite/Magento/Backend/Controller/Adminhtml/System/Config/SaveTest.php
@@ -70,6 +70,14 @@ class SaveTest extends \PHPUnit_Framework_TestCase
      */
     protected $_responseMock;
 
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $_sectionCheckerMock;
+
+    /**
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
     protected function setUp()
     {
         $this->_requestMock = $this->getMock('Magento\Framework\App\Request\Http', array(), array(), '', false, false);
@@ -151,6 +159,14 @@ class SaveTest extends \PHPUnit_Framework_TestCase
             'messageManager' => $this->messageManagerMock
         );
 
+        $this->_sectionCheckerMock = $this->getMock(
+            'Magento\Backend\Controller\Adminhtml\System\ConfigSectionChecker',
+            array(),
+            array(),
+            '',
+            false
+        );
+
         $context = $helper->getObject('Magento\Backend\App\Action\Context', $arguments);
         $this->_controller = $this->getMock(
             'Magento\Backend\Controller\Adminhtml\System\Config\Save',
@@ -158,6 +174,7 @@ class SaveTest extends \PHPUnit_Framework_TestCase
             array(
                 $context,
                 $configStructureMock,
+                $this->_sectionCheckerMock,
                 $this->_configFactoryMock,
                 $this->_cacheMock,
                 new \Magento\Framework\Stdlib\String()
@@ -167,7 +184,7 @@ class SaveTest extends \PHPUnit_Framework_TestCase
 
     public function testIndexActionWithAllowedSection()
     {
-        $this->_sectionMock->expects($this->any())->method('isAllowed')->will($this->returnValue(true));
+        $this->_sectionCheckerMock->expects($this->any())->method('isSectionAllowed')->will($this->returnValue(true));
         $this->messageManagerMock->expects($this->once())->method('addSuccess')->with('You saved the configuration.');
 
         $groups = array('some_key' => 'some_value');
@@ -204,30 +221,9 @@ class SaveTest extends \PHPUnit_Framework_TestCase
         $this->_controller->execute();
     }
 
-    public function testIndexActionWithNotAllowedSection()
-    {
-        $this->_sectionMock->expects($this->any())->method('isAllowed')->will($this->returnValue(false));
-
-        $backendConfigMock = $this->getMock('Magento\Backend\Model\Config', array(), array(), '', false, false);
-        $backendConfigMock->expects($this->never())->method('save');
-        $this->_eventManagerMock->expects($this->never())->method('dispatch');
-        $this->messageManagerMock->expects($this->never())->method('addSuccess');
-        $this->messageManagerMock->expects($this->once())->method('addException');
-
-        $this->_configFactoryMock->expects(
-            $this->any()
-        )->method(
-            'create'
-        )->will(
-            $this->returnValue($backendConfigMock)
-        );
-
-        $this->_controller->execute();
-    }
-
     public function testIndexActionSaveState()
     {
-        $this->_sectionMock->expects($this->any())->method('isAllowed')->will($this->returnValue(false));
+        $this->_sectionCheckerMock->expects($this->any())->method('isSectionAllowed')->will($this->returnValue(false));
         $data = array('some_key' => 'some_value');
 
         $userMock = $this->getMock('Magento\User\Model\User', array(), array(), '', false, false);
@@ -248,7 +244,7 @@ class SaveTest extends \PHPUnit_Framework_TestCase
 
     public function testIndexActionGetGroupForSave()
     {
-        $this->_sectionMock->expects($this->any())->method('isAllowed')->will($this->returnValue(true));
+        $this->_sectionCheckerMock->expects($this->any())->method('isSectionAllowed')->will($this->returnValue(true));
 
         $fixturePath = __DIR__ . '/_files/';
         $groups = require_once $fixturePath . 'groups_array.php';
@@ -299,7 +295,7 @@ class SaveTest extends \PHPUnit_Framework_TestCase
 
     public function testIndexActionSaveAdvanced()
     {
-        $this->_sectionMock->expects($this->any())->method('isAllowed')->will($this->returnValue(true));
+        $this->_sectionCheckerMock->expects($this->any())->method('isSectionAllowed')->will($this->returnValue(true));
 
         $requestParamMap = array(
             array('section', null, 'advanced'),
diff --git a/dev/tests/unit/testsuite/Magento/Backend/Model/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Backend/Model/ConfigTest.php
index 16a334ed1f4133d74a10284044aac63858b0a6b6..e3f89ef42253a0c49a056527c97aff85d92ce3e8 100644
--- a/dev/tests/unit/testsuite/Magento/Backend/Model/ConfigTest.php
+++ b/dev/tests/unit/testsuite/Magento/Backend/Model/ConfigTest.php
@@ -242,6 +242,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         );
 
         $website = $this->getMock('Magento\Store\Model\Website', array(), array(), '', false);
+        $website->expects($this->any())->method('getCode')->will($this->returnValue('website_code'));
         $this->_storeManager->expects($this->any())->method('getWebsite')->will($this->returnValue($website));
         $this->_storeManager->expects($this->any())->method('getWebsites')->will($this->returnValue(array($website)));
         $this->_storeManager->expects($this->any())->method('isSingleStoreMode')->will($this->returnValue(true));
@@ -268,7 +269,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
                 'group_id' => null,
                 'scope' => 'websites',
                 'scope_id' => 0,
-                'scope_code' => 'website',
+                'scope_code' => 'website_code',
                 'field_config' => null,
                 'fieldset_data' => array('key' => null)
             )
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Catalog/Product/Composite/Fieldset/Options/Type/CheckboxTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Catalog/Product/Composite/Fieldset/Options/Type/CheckboxTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0a310bba02bf29114331ffa61c6aeac54f8011dd
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Catalog/Product/Composite/Fieldset/Options/Type/CheckboxTest.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Block\Adminhtml\Catalog\Product\Composite\Fieldset\Options\Type;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class CheckboxTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Bundle\Block\Adminhtml\Catalog\Product\Composite\Fieldset\Options\Type\Checkbox
+     */
+    protected $block;
+
+    public function setUp()
+    {
+        $this->block = (new ObjectManager($this))
+            ->getObject('Magento\Bundle\Block\Adminhtml\Catalog\Product\Composite\Fieldset\Options\Type\Checkbox');
+    }
+
+    public function testSetValidationContainer()
+    {
+        $elementId = 'element-id';
+        $containerId = 'container-id';
+
+        $result = $this->block->setValidationContainer($elementId, $containerId);
+
+        $this->assertContains($elementId, $result);
+        $this->assertContains($containerId, $result);
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Catalog/Product/Composite/Fieldset/Options/Type/MultiTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Catalog/Product/Composite/Fieldset/Options/Type/MultiTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c4346248329086710bce6adc24d792bff4ab7123
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Catalog/Product/Composite/Fieldset/Options/Type/MultiTest.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Block\Adminhtml\Catalog\Product\Composite\Fieldset\Options\Type;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class MultiTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Bundle\Block\Adminhtml\Catalog\Product\Composite\Fieldset\Options\Type\Multi
+     */
+    protected $block;
+
+    public function setUp()
+    {
+        $this->block = (new ObjectManager($this))
+            ->getObject('Magento\Bundle\Block\Adminhtml\Catalog\Product\Composite\Fieldset\Options\Type\Multi');
+    }
+
+    public function testSetValidationContainer()
+    {
+        $elementId = 'element-id';
+        $containerId = 'container-id';
+
+        $result = $this->block->setValidationContainer($elementId, $containerId);
+
+        $this->assertContains($elementId, $result);
+        $this->assertContains($containerId, $result);
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Catalog/Product/Composite/Fieldset/Options/Type/RadioTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Catalog/Product/Composite/Fieldset/Options/Type/RadioTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..609851d15f9df6ac6faf067254478fded6c41c60
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Catalog/Product/Composite/Fieldset/Options/Type/RadioTest.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Block\Adminhtml\Catalog\Product\Composite\Fieldset\Options\Type;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class RadioTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Bundle\Block\Adminhtml\Catalog\Product\Composite\Fieldset\Options\Type\Radio
+     */
+    protected $block;
+
+    public function setUp()
+    {
+        $this->block = (new ObjectManager($this))
+            ->getObject('Magento\Bundle\Block\Adminhtml\Catalog\Product\Composite\Fieldset\Options\Type\Radio');
+    }
+
+    public function testSetValidationContainer()
+    {
+        $elementId = 'element-id';
+        $containerId = 'container-id';
+
+        $result = $this->block->setValidationContainer($elementId, $containerId);
+
+        $this->assertContains($elementId, $result);
+        $this->assertContains($containerId, $result);
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Catalog/Product/Composite/Fieldset/Options/Type/SelectTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Catalog/Product/Composite/Fieldset/Options/Type/SelectTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f24fe781bcd3e7db507698443fcd3665c121e7c2
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Catalog/Product/Composite/Fieldset/Options/Type/SelectTest.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Block\Adminhtml\Catalog\Product\Composite\Fieldset\Options\Type;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class SelectTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Bundle\Block\Adminhtml\Catalog\Product\Composite\Fieldset\Options\Type\Select
+     */
+    protected $block;
+
+    public function setUp()
+    {
+        $this->block = (new ObjectManager($this))
+            ->getObject('Magento\Bundle\Block\Adminhtml\Catalog\Product\Composite\Fieldset\Options\Type\Select');
+    }
+
+    public function testSetValidationContainer()
+    {
+        $elementId = 'element-id';
+        $containerId = 'container-id';
+
+        $result = $this->block->setValidationContainer($elementId, $containerId);
+
+        $this->assertContains($elementId, $result);
+        $this->assertContains($containerId, $result);
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Sales/Order/Items/RendererTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Sales/Order/Items/RendererTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4f1278e2cf3dd480c0f9c7048bc9c84192e6d949
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Sales/Order/Items/RendererTest.php
@@ -0,0 +1,265 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Block\Adminhtml\Sales\Order\Items;
+
+class RendererTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Sales\Model\Order\Item|\PHPUnit_Framework_MockObject_MockObject */
+    protected $orderItem;
+
+    /** @var \Magento\Bundle\Block\Adminhtml\Sales\Order\Items\Renderer $model */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->orderItem = $this->getMock(
+            'Magento\Sales\Model\Order\Item',
+            ['getProductOptions', '__wakeup', 'getParentItem', 'getOrderItem', 'getOrderItemId', 'getId'],
+            [],
+            '',
+            false
+        );
+
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->model = $objectManager->getObject('Magento\Bundle\Block\Adminhtml\Sales\Order\Items\Renderer');
+    }
+
+    /**
+     * @dataProvider getChildrenEmptyItemsDataProvider
+     */
+    public function testGetChildrenEmptyItems($class, $method, $returnClass)
+    {
+        $salesModel = $this->getMock($returnClass, ['getAllItems', '__wakeup'], [], '', false);
+        $salesModel->expects($this->once())->method('getAllItems')->will($this->returnValue([]));
+
+        $item = $this->getMock($class, [$method, 'getOrderItem', '__wakeup'], [], '', false);
+        $item->expects($this->once())->method($method)->will($this->returnValue($salesModel));
+        $item->expects($this->once())->method('getOrderItem')->will($this->returnValue($this->orderItem));
+        $this->orderItem->expects($this->any())->method('getId')->will($this->returnValue(1));
+
+        $this->assertSame(null, $this->model->getChilds($item));
+    }
+
+    public function getChildrenEmptyItemsDataProvider()
+    {
+        return [
+            ['Magento\Sales\Model\Order\Invoice\Item', 'getInvoice', 'Magento\Sales\Model\Order\Invoice'],
+            ['Magento\Sales\Model\Order\Shipment\Item', 'getShipment', 'Magento\Sales\Model\Order\Shipment'],
+            ['Magento\Sales\Model\Order\Creditmemo\Item', 'getCreditmemo', 'Magento\Sales\Model\Order\Creditmemo']
+        ];
+    }
+
+    /**
+     * @dataProvider getChildrenDataProvider
+     */
+    public function testGetChildren($parentItem)
+    {
+        if ($parentItem) {
+            $parentItem = $this->getMock('Magento\Sales\Model\Order\Item', ['getId', '__wakeup'], [], '', false);
+            $parentItem->expects($this->any())->method('getId')->will($this->returnValue(1));
+        }
+        $this->orderItem->expects($this->any())->method('getOrderItem')->will($this->returnSelf());
+        $this->orderItem->expects($this->any())->method('getParentItem')->will($this->returnValue($parentItem));
+        $this->orderItem->expects($this->any())->method('getOrderItemId')->will($this->returnValue(2));
+        $this->orderItem->expects($this->any())->method('getId')->will($this->returnValue(1));
+
+        $salesModel = $this->getMock('Magento\Sales\Model\Order\Invoice', ['getAllItems', '__wakeup'], [], '', false);
+        $salesModel->expects($this->once())->method('getAllItems')->will($this->returnValue([$this->orderItem]));
+
+        $item = $this->getMock(
+            'Magento\Sales\Model\Order\Invoice\Item',
+            ['getInvoice', 'getOrderItem', '__wakeup'],
+            [],
+            '',
+            false
+        );
+        $item->expects($this->once())->method('getInvoice')->will($this->returnValue($salesModel));
+        $item->expects($this->any())->method('getOrderItem')->will($this->returnValue($this->orderItem));
+
+        $this->assertSame([2 => $this->orderItem], $this->model->getChilds($item));
+    }
+
+    public function getChildrenDataProvider()
+    {
+        return [
+            [true],
+            [false],
+        ];
+    }
+
+    /**
+     * @dataProvider isShipmentSeparatelyWithoutItemDataProvider
+     */
+    public function testIsShipmentSeparatelyWithoutItem($productOptions, $result)
+    {
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+
+        $this->assertSame($result, $this->model->isShipmentSeparately());
+    }
+
+    public function isShipmentSeparatelyWithoutItemDataProvider()
+    {
+        return [
+            [['shipment_type' => 1], true],
+            [['shipment_type' => 0], false],
+            [[], false]
+        ];
+    }
+
+    /**
+     * @dataProvider isShipmentSeparatelyWithItemDataProvider
+     */
+    public function testIsShipmentSeparatelyWithItem($productOptions, $result, $parentItem)
+    {
+        if ($parentItem) {
+            $parentItem =
+                $this->getMock('Magento\Sales\Model\Order\Item', ['getProductOptions', '__wakeup'], [], '', false);
+            $parentItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        } else {
+            $this->orderItem->expects($this->any())->method('getProductOptions')
+                ->will($this->returnValue($productOptions));
+        }
+        $this->orderItem->expects($this->any())->method('getParentItem')->will($this->returnValue($parentItem));
+        $this->orderItem->expects($this->any())->method('getOrderItem')->will($this->returnSelf());
+
+        $this->assertSame($result, $this->model->isShipmentSeparately($this->orderItem));
+    }
+
+    public function isShipmentSeparatelyWithItemDataProvider()
+    {
+        return [
+            [['shipment_type' => 1], false, false],
+            [['shipment_type' => 0], true, false],
+            [['shipment_type' => 1], true, true],
+            [['shipment_type' => 0], false, true],
+        ];
+    }
+
+    /**
+     * @dataProvider isChildCalculatedWithoutItemDataProvider
+     */
+    public function testIsChildCalculatedWithoutItem($productOptions, $result)
+    {
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+
+        $this->assertSame($result, $this->model->isChildCalculated());
+    }
+
+    public function isChildCalculatedWithoutItemDataProvider()
+    {
+        return [
+            [['product_calculations' => 0], true],
+            [['product_calculations' => 1], false],
+            [[], false],
+        ];
+    }
+
+    /**
+     * @dataProvider isChildCalculatedWithItemDataProvider
+     */
+    public function testIsChildCalculatedWithItem($productOptions, $result, $parentItem)
+    {
+        if ($parentItem) {
+            $parentItem =
+                $this->getMock('Magento\Sales\Model\Order\Item', ['getProductOptions', '__wakeup'], [], '', false);
+            $parentItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        } else {
+            $this->orderItem->expects($this->any())->method('getProductOptions')
+                ->will($this->returnValue($productOptions));
+        }
+        $this->orderItem->expects($this->any())->method('getParentItem')->will($this->returnValue($parentItem));
+        $this->orderItem->expects($this->any())->method('getOrderItem')->will($this->returnSelf());
+
+        $this->assertSame($result, $this->model->isChildCalculated($this->orderItem));
+    }
+
+    public function isChildCalculatedWithItemDataProvider()
+    {
+        return [
+            [['product_calculations' => 0], false, false],
+            [['product_calculations' => 1], true, false],
+            [['product_calculations' => 0], true, true],
+            [['product_calculations' => 1], false, true],
+        ];
+    }
+
+    /**
+     * @dataProvider getSelectionAttributesDataProvider
+     */
+    public function testGetSelectionAttributes($productOptions, $result)
+    {
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        $this->assertSame($result, $this->model->getSelectionAttributes($this->orderItem));
+    }
+
+    public function getSelectionAttributesDataProvider()
+    {
+        return [
+            [[], null],
+            [['bundle_selection_attributes' => 'a:1:{i:0;i:1;}'], [0 => 1]],
+        ];
+    }
+
+    public function testGetOrderOptions()
+    {
+        $productOptions = [
+            'options' => ['options'],
+            'additional_options' => ['additional_options'],
+            'attributes_info' => ['attributes_info']
+        ];
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        $this->assertEquals(['attributes_info', 'options', 'additional_options'], $this->model->getOrderOptions());
+    }
+
+    public function testGetOrderItem()
+    {
+        $this->model->setItem($this->orderItem);
+        $this->assertSame($this->orderItem, $this->model->getOrderItem());
+    }
+
+    /**
+     * @dataProvider canShowPriceInfoDataProvider
+     */
+    public function testCanShowPriceInfo($parentItem, $productOptions, $result)
+    {
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getOrderItem')->will($this->returnSelf());
+        $this->orderItem->expects($this->any())->method('getParentItem')->will($this->returnValue($parentItem));
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+
+        $this->assertSame($result, $this->model->canShowPriceInfo($this->orderItem));
+    }
+
+    public function canShowPriceInfoDataProvider()
+    {
+        return [
+            [true, ['product_calculations' => 0], true],
+            [false, [], true],
+            [false, ['product_calculations' => 0], false],
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Sales/Order/View/Items/RendererTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Sales/Order/View/Items/RendererTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c3c0d11001d4e3cc1feac7d15b81f79115da492f
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Block/Adminhtml/Sales/Order/View/Items/RendererTest.php
@@ -0,0 +1,196 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Block\Adminhtml\Sales\Order\View\Items;
+
+class RendererTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Sales\Model\Order\Item|\PHPUnit_Framework_MockObject_MockObject */
+    protected $orderItem;
+
+    /** @var \Magento\Bundle\Block\Adminhtml\Sales\Order\View\Items\Renderer $model */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->orderItem = $this->getMock(
+            'Magento\Sales\Model\Order\Item',
+            ['getProductOptions', '__wakeup', 'getParentItem', 'getOrderItem'],
+            [],
+            '',
+            false
+        );
+
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->model = $objectManager->getObject('Magento\Bundle\Block\Adminhtml\Sales\Order\View\Items\Renderer');
+    }
+
+    /**
+     * @dataProvider isShipmentSeparatelyWithoutItemDataProvider
+     */
+    public function testIsShipmentSeparatelyWithoutItem($productOptions, $result)
+    {
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+
+        $this->assertSame($result, $this->model->isShipmentSeparately());
+    }
+
+    public function isShipmentSeparatelyWithoutItemDataProvider()
+    {
+        return [
+            [['shipment_type' => 1], true],
+            [['shipment_type' => 0], false],
+            [[], false]
+        ];
+    }
+
+    /**
+     * @dataProvider isShipmentSeparatelyWithItemDataProvider
+     */
+    public function testIsShipmentSeparatelyWithItem($productOptions, $result, $parentItem)
+    {
+        if ($parentItem) {
+            $parentItem =
+                $this->getMock('Magento\Sales\Model\Order\Item', ['getProductOptions', '__wakeup'], [], '', false);
+            $parentItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        } else {
+            $this->orderItem->expects($this->any())->method('getProductOptions')
+                ->will($this->returnValue($productOptions));
+        }
+        $this->orderItem->expects($this->any())->method('getParentItem')->will($this->returnValue($parentItem));
+        $this->orderItem->expects($this->any())->method('getOrderItem')->will($this->returnSelf());
+
+        $this->assertSame($result, $this->model->isShipmentSeparately($this->orderItem));
+    }
+
+    public function isShipmentSeparatelyWithItemDataProvider()
+    {
+        return [
+            [['shipment_type' => 1], false, false],
+            [['shipment_type' => 0], true, false],
+            [['shipment_type' => 1], true, true],
+            [['shipment_type' => 0], false, true],
+        ];
+    }
+
+    /**
+     * @dataProvider isChildCalculatedWithoutItemDataProvider
+     */
+    public function testIsChildCalculatedWithoutItem($productOptions, $result)
+    {
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+
+        $this->assertSame($result, $this->model->isChildCalculated());
+    }
+
+    public function isChildCalculatedWithoutItemDataProvider()
+    {
+        return [
+            [['product_calculations' => 0], true],
+            [['product_calculations' => 1], false],
+            [[], false],
+        ];
+    }
+
+    /**
+     * @dataProvider isChildCalculatedWithItemDataProvider
+     */
+    public function testIsChildCalculatedWithItem($productOptions, $result, $parentItem)
+    {
+        if ($parentItem) {
+            $parentItem =
+                $this->getMock('Magento\Sales\Model\Order\Item', ['getProductOptions', '__wakeup'], [], '', false);
+            $parentItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        } else {
+            $this->orderItem->expects($this->any())->method('getProductOptions')
+                ->will($this->returnValue($productOptions));
+        }
+        $this->orderItem->expects($this->any())->method('getParentItem')->will($this->returnValue($parentItem));
+        $this->orderItem->expects($this->any())->method('getOrderItem')->will($this->returnSelf());
+
+        $this->assertSame($result, $this->model->isChildCalculated($this->orderItem));
+    }
+
+    public function isChildCalculatedWithItemDataProvider()
+    {
+        return [
+            [['product_calculations' => 0], false, false],
+            [['product_calculations' => 1], true, false],
+            [['product_calculations' => 0], true, true],
+            [['product_calculations' => 1], false, true],
+        ];
+    }
+
+    /**
+     * @dataProvider getSelectionAttributesDataProvider
+     */
+    public function testGetSelectionAttributes($productOptions, $result)
+    {
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        $this->assertSame($result, $this->model->getSelectionAttributes($this->orderItem));
+    }
+
+    public function getSelectionAttributesDataProvider()
+    {
+        return [
+            [[], null],
+            [['bundle_selection_attributes' => 'a:1:{i:0;i:1;}'], [0 => 1]],
+        ];
+    }
+
+    public function testGetOrderOptions()
+    {
+        $productOptions = [
+            'options' => ['options'],
+            'additional_options' => ['additional_options'],
+            'attributes_info' => ['attributes_info']
+        ];
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        $this->assertEquals(['attributes_info', 'options', 'additional_options'], $this->model->getOrderOptions());
+    }
+
+    /**
+     * @dataProvider canShowPriceInfoDataProvider
+     */
+    public function testCanShowPriceInfo($parentItem, $productOptions, $result)
+    {
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getOrderItem')->will($this->returnSelf());
+        $this->orderItem->expects($this->any())->method('getParentItem')->will($this->returnValue($parentItem));
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+
+        $this->assertSame($result, $this->model->canShowPriceInfo($this->orderItem));
+    }
+
+    public function canShowPriceInfoDataProvider()
+    {
+        return [
+            [true, ['product_calculations' => 0], true],
+            [false, [], true],
+            [false, ['product_calculations' => 0], false],
+        ];
+    }
+}
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Block/Sales/Order/Items/RendererTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Block/Sales/Order/Items/RendererTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b1a89097ae81a56fd502ee47207547ce8177a432
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Block/Sales/Order/Items/RendererTest.php
@@ -0,0 +1,247 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Block\Sales\Order\Items;
+
+class RendererTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Sales\Model\Order\Item|\PHPUnit_Framework_MockObject_MockObject */
+    protected $orderItem;
+
+    /** @var \Magento\Bundle\Block\Sales\Order\Items\Renderer $model */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->orderItem = $this->getMock(
+            'Magento\Sales\Model\Order\Item',
+            ['getProductOptions', '__wakeup', 'getParentItem', 'getOrderItem', 'getOrderItemId', 'getId'],
+            [],
+            '',
+            false
+        );
+
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->model = $objectManager->getObject('Magento\Bundle\Block\Sales\Order\Items\Renderer');
+    }
+
+    /**
+     * @dataProvider getChildrenEmptyItemsDataProvider
+     */
+    public function testGetChildrenEmptyItems($class, $method, $returnClass)
+    {
+        $salesModel = $this->getMock($returnClass, ['getAllItems', '__wakeup'], [], '', false);
+        $salesModel->expects($this->once())->method('getAllItems')->will($this->returnValue([]));
+
+        $item = $this->getMock($class, [$method, 'getOrderItem', '__wakeup'], [], '', false);
+        $item->expects($this->once())->method($method)->will($this->returnValue($salesModel));
+        $item->expects($this->once())->method('getOrderItem')->will($this->returnValue($this->orderItem));
+        $this->orderItem->expects($this->any())->method('getId')->will($this->returnValue(1));
+
+        $this->assertSame(null, $this->model->getChilds($item));
+    }
+
+    public function getChildrenEmptyItemsDataProvider()
+    {
+        return [
+            ['Magento\Sales\Model\Order\Invoice\Item', 'getInvoice', 'Magento\Sales\Model\Order\Invoice'],
+            ['Magento\Sales\Model\Order\Shipment\Item', 'getShipment', 'Magento\Sales\Model\Order\Shipment'],
+            ['Magento\Sales\Model\Order\Creditmemo\Item', 'getCreditmemo', 'Magento\Sales\Model\Order\Creditmemo']
+        ];
+    }
+
+    /**
+     * @dataProvider getChildrenDataProvider
+     */
+    public function testGetChildren($parentItem)
+    {
+        if ($parentItem) {
+            $parentItem = $this->getMock('Magento\Sales\Model\Order\Item', ['getId', '__wakeup'], [], '', false);
+            $parentItem->expects($this->any())->method('getId')->will($this->returnValue(1));
+        }
+        $this->orderItem->expects($this->any())->method('getOrderItem')->will($this->returnSelf());
+        $this->orderItem->expects($this->any())->method('getParentItem')->will($this->returnValue($parentItem));
+        $this->orderItem->expects($this->any())->method('getOrderItemId')->will($this->returnValue(2));
+        $this->orderItem->expects($this->any())->method('getId')->will($this->returnValue(1));
+
+        $salesModel = $this->getMock('Magento\Sales\Model\Order\Invoice', ['getAllItems', '__wakeup'], [], '', false);
+        $salesModel->expects($this->once())->method('getAllItems')->will($this->returnValue([$this->orderItem]));
+
+        $item = $this->getMock(
+            'Magento\Sales\Model\Order\Invoice\Item',
+            ['getInvoice', 'getOrderItem', '__wakeup'],
+            [],
+            '',
+            false
+        );
+        $item->expects($this->once())->method('getInvoice')->will($this->returnValue($salesModel));
+        $item->expects($this->any())->method('getOrderItem')->will($this->returnValue($this->orderItem));
+
+        $this->assertSame([2 => $this->orderItem], $this->model->getChilds($item));
+    }
+
+    public function getChildrenDataProvider()
+    {
+        return [
+            [true],
+            [false],
+        ];
+    }
+
+    /**
+     * @dataProvider isShipmentSeparatelyWithoutItemDataProvider
+     */
+    public function testIsShipmentSeparatelyWithoutItem($productOptions, $result)
+    {
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+
+        $this->assertSame($result, $this->model->isShipmentSeparately());
+    }
+
+    public function isShipmentSeparatelyWithoutItemDataProvider()
+    {
+        return [
+            [['shipment_type' => 1], true],
+            [['shipment_type' => 0], false],
+            [[], false]
+        ];
+    }
+
+    /**
+     * @dataProvider isShipmentSeparatelyWithItemDataProvider
+     */
+    public function testIsShipmentSeparatelyWithItem($productOptions, $result, $parentItem)
+    {
+        if ($parentItem) {
+            $parentItem =
+                $this->getMock('Magento\Sales\Model\Order\Item', ['getProductOptions', '__wakeup'], [], '', false);
+            $parentItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        } else {
+            $this->orderItem->expects($this->any())->method('getProductOptions')
+                ->will($this->returnValue($productOptions));
+        }
+        $this->orderItem->expects($this->any())->method('getParentItem')->will($this->returnValue($parentItem));
+        $this->orderItem->expects($this->any())->method('getOrderItem')->will($this->returnSelf());
+
+        $this->assertSame($result, $this->model->isShipmentSeparately($this->orderItem));
+    }
+
+    public function isShipmentSeparatelyWithItemDataProvider()
+    {
+        return [
+            [['shipment_type' => 1], false, false],
+            [['shipment_type' => 0], true, false],
+            [['shipment_type' => 1], true, true],
+            [['shipment_type' => 0], false, true],
+        ];
+    }
+
+    /**
+     * @dataProvider isChildCalculatedWithoutItemDataProvider
+     */
+    public function testIsChildCalculatedWithoutItem($productOptions, $result)
+    {
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+
+        $this->assertSame($result, $this->model->isChildCalculated());
+    }
+
+    public function isChildCalculatedWithoutItemDataProvider()
+    {
+        return [
+            [['product_calculations' => 0], true],
+            [['product_calculations' => 1], false],
+            [[], false],
+        ];
+    }
+
+    /**
+     * @dataProvider isChildCalculatedWithItemDataProvider
+     */
+    public function testIsChildCalculatedWithItem($productOptions, $result, $parentItem)
+    {
+        if ($parentItem) {
+            $parentItem =
+                $this->getMock('Magento\Sales\Model\Order\Item', ['getProductOptions', '__wakeup'], [], '', false);
+            $parentItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        } else {
+            $this->orderItem->expects($this->any())->method('getProductOptions')
+                ->will($this->returnValue($productOptions));
+        }
+        $this->orderItem->expects($this->any())->method('getParentItem')->will($this->returnValue($parentItem));
+        $this->orderItem->expects($this->any())->method('getOrderItem')->will($this->returnSelf());
+
+        $this->assertSame($result, $this->model->isChildCalculated($this->orderItem));
+    }
+
+    public function isChildCalculatedWithItemDataProvider()
+    {
+        return [
+            [['product_calculations' => 0], false, false],
+            [['product_calculations' => 1], true, false],
+            [['product_calculations' => 0], true, true],
+            [['product_calculations' => 1], false, true],
+        ];
+    }
+
+    /**
+     * @dataProvider getSelectionAttributesDataProvider
+     */
+    public function testGetSelectionAttributes($productOptions, $result)
+    {
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        $this->assertSame($result, $this->model->getSelectionAttributes($this->orderItem));
+    }
+
+    public function getSelectionAttributesDataProvider()
+    {
+        return [
+            [[], null],
+            [['bundle_selection_attributes' => 'a:1:{i:0;i:1;}'], [0 => 1]],
+        ];
+    }
+
+    /**
+     * @dataProvider canShowPriceInfoDataProvider
+     */
+    public function testCanShowPriceInfo($parentItem, $productOptions, $result)
+    {
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getOrderItem')->will($this->returnSelf());
+        $this->orderItem->expects($this->any())->method('getParentItem')->will($this->returnValue($parentItem));
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+
+        $this->assertSame($result, $this->model->canShowPriceInfo($this->orderItem));
+    }
+
+    public function canShowPriceInfoDataProvider()
+    {
+        return [
+            [true, ['product_calculations' => 0], true],
+            [false, [], true],
+            [false, ['product_calculations' => 0], false],
+        ];
+    }
+}
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Helper/Catalog/Product/ConfigurationTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Helper/Catalog/Product/ConfigurationTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..151a87c78ff21d9c721c108c8ca0fb77a216f3e8
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Helper/Catalog/Product/ConfigurationTest.php
@@ -0,0 +1,220 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Helper\Catalog\Product;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class ConfigurationTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Core\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */
+    protected $coreData;
+
+    /** @var \Magento\Catalog\Helper\Product\Configuration|\PHPUnit_Framework_MockObject_MockObject */
+    protected $productConfiguration;
+
+    /** @var \Magento\Framework\Escaper|\PHPUnit_Framework_MockObject_MockObject */
+    protected $escaper;
+
+    /** @var \Magento\Bundle\Helper\Catalog\Product\Configuration */
+    protected $helper;
+
+    /** @var \Magento\Catalog\Model\Product\Configuration\Item\ItemInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $item;
+
+    protected function setUp()
+    {
+        $this->coreData = $this->getMock('Magento\Core\Helper\Data', ['currency'], [], '', false);
+        $this->productConfiguration = $this->getMock('Magento\Catalog\Helper\Product\Configuration', [], [], '', false);
+        $this->escaper = $this->getMock('Magento\Framework\Escaper', ['escapeHtml'], [], '', false);
+        $this->item = $this->getMock(
+            'Magento\Catalog\Model\Product\Configuration\Item\ItemInterface',
+            ['getQty', 'getProduct', 'getOptionByCode', 'getFileDownloadParams']
+        );
+
+        $this->helper = (new ObjectManager($this))->getObject(
+            'Magento\Bundle\Helper\Catalog\Product\Configuration',
+            [
+                'coreData' => $this->coreData,
+                'productConfiguration' => $this->productConfiguration,
+                'escaper' => $this->escaper,
+            ]
+        );
+    }
+
+    public function testGetSelectionQty()
+    {
+        $selectionId = 15;
+        $selectionQty = 35;
+        $product = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false);
+        $option = $this->getMock('Magento\Catalog\Model\Product\Option', ['__wakeup', 'getValue'], [], '', false);
+
+        $product->expects($this->once())->method('getCustomOption')->with('selection_qty_' . $selectionId)
+            ->will($this->returnValue($option));
+        $option->expects($this->once())->method('getValue')->will($this->returnValue($selectionQty));
+
+        $this->assertEquals($selectionQty, $this->helper->getSelectionQty($product, $selectionId));
+    }
+
+    public function testGetSelectionQtyIfCustomOptionIsNotSet()
+    {
+        $selectionId = 15;
+        $product = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false);
+
+        $product->expects($this->once())->method('getCustomOption')->with('selection_qty_' . $selectionId)
+            ->will($this->returnValue(null));
+
+        $this->assertEquals(0, $this->helper->getSelectionQty($product, $selectionId));
+    }
+
+    /**
+     * @covers \Magento\Bundle\Helper\Catalog\Product\Configuration::getSelectionFinalPrice
+     */
+    public function testGetSelectionFinalPrice()
+    {
+        $itemQty = 2;
+
+        $product = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false);
+        $price = $this->getMock('Magento\Bundle\Model\Product\Price', [], [], '', false);
+        $selectionProduct = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false);
+
+        $selectionProduct->expects($this->once())->method('unsetData')->with('final_price');
+        $this->item->expects($this->once())->method('getProduct')->will($this->returnValue($product));
+        $this->item->expects($this->once())->method('getQty')->will($this->returnValue($itemQty));
+        $product->expects($this->once())->method('getPriceModel')->will($this->returnValue($price));
+        $price->expects($this->once())->method('getSelectionFinalTotalPrice')
+            ->with($product, $selectionProduct, $itemQty, 0, false, true);
+
+        $this->helper->getSelectionFinalPrice($this->item, $selectionProduct);
+    }
+
+    public function testGetBundleOptionsEmptyBundleOptionsIds()
+    {
+        $typeInstance = $this->getMock('Magento\Bundle\Model\Product\Type', [], [], '', false);
+        $product = $this->getMock('Magento\Catalog\Model\Product', ['getTypeInstance', '__wakeup'], [], '', false);
+
+        $product->expects($this->once())->method('getTypeInstance')->will($this->returnValue($typeInstance));
+        $this->item->expects($this->once())->method('getProduct')->will($this->returnValue($product));
+        $this->item->expects($this->once())->method('getOptionByCode')->with('bundle_option_ids')
+            ->will($this->returnValue(null));
+
+        $this->assertEquals([], $this->helper->getBundleOptions($this->item));
+    }
+
+    public function testGetBundleOptionsEmptyBundleSelectionIds()
+    {
+        $optionIds = 'a:1:{i:0;i:1;}';
+
+        $collection = $this->getMock('Magento\Bundle\Model\Resource\Option\Collection', [], [], '', false);
+        $product = $this->getMock('Magento\Catalog\Model\Product', ['getTypeInstance', '__wakeup'], [], '', false);
+        $typeInstance = $this->getMock('Magento\Bundle\Model\Product\Type', ['getOptionsByIds'], [], '', false);
+        $selectionOption =
+            $this->getMock('\Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface', ['getValue']);
+        $itemOption =
+            $this->getMock('\Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface', ['getValue']);
+
+        $selectionOption->expects($this->once())->method('getValue')->will($this->returnValue(''));
+        $itemOption->expects($this->once())->method('getValue')->will($this->returnValue($optionIds));
+        $typeInstance->expects($this->once())->method('getOptionsByIds')->with(unserialize($optionIds), $product)
+            ->will($this->returnValue($collection));
+        $product->expects($this->once())->method('getTypeInstance')->will($this->returnValue($typeInstance));
+        $this->item->expects($this->once())->method('getProduct')->will($this->returnValue($product));
+        $this->item->expects($this->at(1))->method('getOptionByCode')->with('bundle_option_ids')
+            ->will($this->returnValue($itemOption));
+        $this->item->expects($this->at(2))->method('getOptionByCode')->with('bundle_selection_ids')
+            ->will($this->returnValue($selectionOption));
+
+        $this->assertEquals([], $this->helper->getBundleOptions($this->item));
+    }
+
+    public function testGetOptions()
+    {
+        $optionIds = 'a:1:{i:0;i:1;}';
+        $selectionIds = 'a:1:{i:0;s:1:"2";}';
+        $selectionId = '2';
+        $product = $this->getMock(
+            'Magento\Catalog\Model\Product',
+            ['getTypeInstance', '__wakeup', 'getCustomOption', 'getSelectionId', 'getName', 'getPriceModel'],
+            [],
+            '',
+            false
+        );
+        $typeInstance = $this->getMock(
+            'Magento\Bundle\Model\Product\Type',
+            ['getOptionsByIds', 'getSelectionsByIds'],
+            [],
+            '',
+            false
+        );
+        $priceModel =
+            $this->getMock('Magento\Bundle\Model\Product\Price', ['getSelectionFinalTotalPrice'], [], '', false);
+        $selectionQty =
+            $this->getMock('Magento\Sales\Model\Quote\Item\Option', ['getValue', '__wakeup'], [], '', false);
+        $bundleOption =
+            $this->getMock('Magento\Bundle\Model\Option', ['getSelections', 'getTitle', '__wakeup'], [], '', false);
+        $selectionOption =
+            $this->getMock('\Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface', ['getValue']);
+        $collection =
+            $this->getMock('Magento\Bundle\Model\Resource\Option\Collection', ['appendSelections'], [], '', false);
+        $itemOption =
+            $this->getMock('\Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface', ['getValue']);
+        $collection2 = $this->getMock('Magento\Bundle\Model\Resource\Selection\Collection', [], [], '', false);
+
+        $this->escaper->expects($this->once())->method('escapeHtml')->with('name')->will($this->returnValue('name'));
+        $this->coreData->expects($this->once())->method('currency')->with(15)
+            ->will($this->returnValue('<span class="price">$15.00</span>'));
+        $priceModel->expects($this->once())->method('getSelectionFinalTotalPrice')->will($this->returnValue(15));
+        $selectionQty->expects($this->any())->method('getValue')->will($this->returnValue(1));
+        $bundleOption->expects($this->any())->method('getSelections')->will($this->returnValue([$product]));
+        $bundleOption->expects($this->once())->method('getTitle')->will($this->returnValue('title'));
+        $selectionOption->expects($this->once())->method('getValue')->will($this->returnValue($selectionIds));
+        $collection->expects($this->once())->method('appendSelections')->with($collection2, true)
+            ->will($this->returnValue([$bundleOption]));
+        $itemOption->expects($this->once())->method('getValue')->will($this->returnValue($optionIds));
+        $typeInstance->expects($this->once())->method('getOptionsByIds')->with(unserialize($optionIds), $product)
+            ->will($this->returnValue($collection));
+        $typeInstance->expects($this->once())->method('getSelectionsByIds')->with(unserialize($selectionIds), $product)
+            ->will($this->returnValue($collection2));
+        $product->expects($this->once())->method('getTypeInstance')->will($this->returnValue($typeInstance));
+        $product->expects($this->any())->method('getCustomOption')->with('selection_qty_' . $selectionId)
+            ->will($this->returnValue($selectionQty));
+        $product->expects($this->any())->method('getSelectionId')->will($this->returnValue($selectionId));
+        $product->expects($this->once())->method('getName')->will($this->returnValue('name'));
+        $product->expects($this->once())->method('getPriceModel')->will($this->returnValue($priceModel));
+        $this->item->expects($this->any())->method('getProduct')->will($this->returnValue($product));
+        $this->item->expects($this->at(1))->method('getOptionByCode')->with('bundle_option_ids')
+            ->will($this->returnValue($itemOption));
+        $this->item->expects($this->at(2))->method('getOptionByCode')->with('bundle_selection_ids')
+            ->will($this->returnValue($selectionOption));
+        $this->productConfiguration->expects($this->once())->method('getCustomOptions')->with($this->item)
+            ->will($this->returnValue([0 => ['label' => 'title', 'value' => 'value']]));
+
+        $this->assertEquals(
+            [
+                0 => ['label' => 'title', 'value' => [0 => '1 x name <span class="price">$15.00</span>']],
+                1 => ['label' => 'title', 'value' => 'value']
+            ],
+            $this->helper->getOptions($this->item)
+        );
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Helper/DataTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Helper/DataTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d668cb5ed3b226305832c08ecf3bd1c27a1f83de
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Helper/DataTest.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Helper;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class DataTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\ProductTypes\ConfigInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $config;
+
+    /**
+     * @var \Magento\Bundle\Helper\Data
+     */
+    protected $helper;
+
+    protected function setUp()
+    {
+        $this->config = $this->getMock('Magento\Catalog\Model\ProductTypes\ConfigInterface');
+        $this->helper = (new ObjectManager($this))->getObject(
+            'Magento\Bundle\Helper\Data',
+            ['config' => $this->config]
+        );
+    }
+
+    public function testGetAllowedSelectionTypes()
+    {
+        $configData = ['allowed_selection_types' => ['foo', 'bar', 'baz']];
+        $this->config->expects($this->once())->method('getType')->with('bundle')->will($this->returnValue($configData));
+
+        $this->assertEquals($configData['allowed_selection_types'], $this->helper->getAllowedSelectionTypes());
+    }
+
+    public function testGetAllowedSelectionTypesIfTypesIsNotSet()
+    {
+        $configData = [];
+        $this->config->expects($this->once())->method('getType')
+            ->with(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE)
+            ->will($this->returnValue($configData));
+
+        $this->assertEquals([], $this->helper->getAllowedSelectionTypes());
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Model/OptionTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Model/OptionTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..355a033db2dbbf7622c5f0fe741d9e2662294f63
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Model/OptionTest.php
@@ -0,0 +1,181 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Model;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class OptionTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $selectionFirst;
+
+    /**
+     * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $selectionSecond;
+
+    /**
+     * @var \Magento\Framework\Model\Resource\AbstractResource|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $resource;
+
+    /**
+     * @var \Magento\Bundle\Model\Option
+     */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->selectionFirst = $this->getMock(
+            'Magento\Catalog\Model\Product',
+            ['__wakeup', 'isSaleable', 'getIsDefault', 'getSelectionId'],
+            [],
+            '',
+            false
+        );
+        $this->selectionSecond = $this->getMock(
+            'Magento\Catalog\Model\Product',
+            ['__wakeup', 'isSaleable', 'getIsDefault', 'getSelectionId'],
+            [],
+            '',
+            false
+        );
+        $this->resource = $this->getMock(
+            'Magento\Framework\Model\Resource\AbstractResource',
+            ['_construct', '_getReadAdapter', '_getWriteAdapter', 'getIdFieldName', 'getSearchableData'],
+            [],
+            '',
+            false
+        );
+        $this->model = (new ObjectManager($this))->getObject('Magento\Bundle\Model\Option', [
+            'resource' => $this->resource,
+        ]);
+    }
+
+    /**
+     * @covers \Magento\Bundle\Model\Option::addSelection
+     */
+    public function testAddSelection()
+    {
+        $this->model->addSelection($this->selectionFirst);
+
+        $this->assertContains($this->selectionFirst, $this->model->getSelections());
+    }
+
+    public function testIsSaleablePositive()
+    {
+        $this->selectionFirst->expects($this->any())->method('isSaleable')->will($this->returnValue(true));
+        $this->selectionSecond->expects($this->any())->method('isSaleable')->will($this->returnValue(false));
+
+        $this->model->setSelections([$this->selectionFirst, $this->selectionSecond]);
+        $this->assertTrue($this->model->isSaleable());
+    }
+
+    public function testIsSaleableNegative()
+    {
+        $this->selectionFirst->expects($this->any())->method('isSaleable')->will($this->returnValue(false));
+        $this->selectionSecond->expects($this->any())->method('isSaleable')->will($this->returnValue(false));
+
+        $this->model->setSelections([$this->selectionFirst, $this->selectionSecond]);
+        $this->assertFalse($this->model->isSaleable());
+    }
+
+    public function testGetDefaultSelection()
+    {
+        $this->selectionFirst->expects($this->any())->method('getIsDefault')->will($this->returnValue(true));
+        $this->selectionSecond->expects($this->any())->method('getIsDefault')->will($this->returnValue(false));
+
+        $this->model->setSelections([$this->selectionFirst, $this->selectionSecond]);
+        $this->assertEquals($this->selectionFirst, $this->model->getDefaultSelection());
+    }
+
+    public function testGetDefaultSelectionNegative()
+    {
+        $this->selectionFirst->expects($this->any())->method('getIsDefault')->will($this->returnValue(false));
+        $this->selectionSecond->expects($this->any())->method('getIsDefault')->will($this->returnValue(false));
+
+        $this->model->setSelections([$this->selectionFirst, $this->selectionSecond]);
+        $this->assertNull($this->model->getDefaultSelection());
+    }
+
+    /**
+     * @param string $type
+     * @param bool $expectedValue
+     * @dataProvider dataProviderForIsMultiSelection
+     */
+    public function testIsMultiSelection($type, $expectedValue)
+    {
+        $this->model->setType($type);
+
+        $this->assertEquals($expectedValue, $this->model->isMultiSelection());
+    }
+
+    /**
+     * @return array
+     */
+    public function dataProviderForIsMultiSelection()
+    {
+        return [
+            ['checkbox', true],
+            ['multi', true],
+            ['some_type', false],
+        ];
+    }
+
+    public function testGetSearchableData()
+    {
+        $productId = 15;
+        $storeId = 1;
+        $data = 'data';
+
+        $this->resource->expects($this->any())->method('getSearchableData')->with($productId, $storeId)
+            ->will($this->returnValue($data));
+
+        $this->assertEquals($data, $this->model->getSearchableData($productId, $storeId));
+    }
+
+    public function testGetSelectionById()
+    {
+        $selectionId = 15;
+
+        $this->selectionFirst->expects($this->any())->method('getSelectionId')->will($this->returnValue($selectionId));
+        $this->selectionSecond->expects($this->any())->method('getSelectionId')->will($this->returnValue(16));
+
+        $this->model->setSelections([$this->selectionFirst, $this->selectionSecond]);
+        $this->assertEquals($this->selectionFirst, $this->model->getSelectionById($selectionId));
+    }
+
+    public function testGetSelectionByIdNegative()
+    {
+        $selectionId = 15;
+
+        $this->selectionFirst->expects($this->any())->method('getSelectionId')->will($this->returnValue(16));
+        $this->selectionSecond->expects($this->any())->method('getSelectionId')->will($this->returnValue(17));
+
+        $this->model->setSelections([$this->selectionFirst, $this->selectionSecond]);
+        $this->assertNull($this->model->getSelectionById($selectionId));
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Model/Plugin/PriceBackendTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Model/Plugin/PriceBackendTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6f306983a2d7786d3e70c4c3303872c919a4a90a
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Model/Plugin/PriceBackendTest.php
@@ -0,0 +1,97 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Model\Plugin;
+
+
+use Magento\Bundle\Model\Product\Price;
+use Magento\Catalog\Model\Product\Type;
+use Magento\TestFramework\Helper\ObjectManager;
+
+
+class PriceBackendTest extends \PHPUnit_Framework_TestCase
+{
+    const CLOSURE_VALUE = 'CLOSURE';
+    /** @var  PriceBackend */
+    private $priceBackendPlugin;
+    /** @var  \PHPUnit_Framework_MockObject_MockObject */
+    private $priceAttributeMock;
+    /** @var  \Closure */
+    private $closure;
+    /** @var  \PHPUnit_Framework_MockObject_MockObject */
+    private $productMock;
+
+    protected function setUp()
+    {
+        $objectManager = new ObjectManager($this);
+        $this->priceBackendPlugin = $objectManager->getObject('\Magento\Bundle\Model\Plugin\PriceBackend');
+
+        $this->closure = function () {
+            return static::CLOSURE_VALUE;
+        };
+        $this->priceAttributeMock = $this->getMockBuilder('Magento\Catalog\Model\Product\Attribute\Backend\Price')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->productMock = $this->getMockBuilder('Magento\Catalog\Model\Product')
+            ->disableOriginalConstructor()
+            ->setMethods(['getTypeId', 'getPriceType', '__wakeUp'])
+            ->getMock();
+    }
+
+    /**
+     * @dataProvider aroundValidateDataProvider
+     *
+     * @param $typeId
+     * @param $priceType
+     * @param $expectedResult
+     */
+    public function testAroundValidate($typeId, $priceType, $expectedResult)
+    {
+        $this->productMock->expects($this->any())->method('getTypeId')->will($this->returnValue($typeId));
+        $this->productMock->expects($this->any())->method('getPriceType')->will($this->returnValue($priceType));
+        $result = $this->priceBackendPlugin->aroundValidate(
+            $this->priceAttributeMock,
+            $this->closure,
+            $this->productMock
+        );
+        $this->assertEquals($expectedResult, $result);
+    }
+
+    /**
+     * Data provider for testAroundValidate
+     *
+     * @return array
+     */
+    public function aroundValidateDataProvider()
+    {
+        return array(
+            ['type' => Type::TYPE_SIMPLE, 'priceType' => Price::PRICE_TYPE_FIXED, 'result' => static::CLOSURE_VALUE],
+            ['type' => Type::TYPE_SIMPLE, 'priceType' => Price::PRICE_TYPE_DYNAMIC, 'result' => static::CLOSURE_VALUE],
+            ['type' => Type::TYPE_BUNDLE, 'priceType' => Price::PRICE_TYPE_FIXED, 'result' => static::CLOSURE_VALUE],
+            ['type' => Type::TYPE_BUNDLE, 'priceType' => Price::PRICE_TYPE_DYNAMIC, 'result' => true],
+            ['type' => Type::TYPE_VIRTUAL, 'priceType' => Price::PRICE_TYPE_FIXED, 'result' => static::CLOSURE_VALUE],
+            ['type' => Type::TYPE_VIRTUAL, 'priceType' => Price::PRICE_TYPE_DYNAMIC, 'result' => static::CLOSURE_VALUE],
+        );
+    }
+}
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Model/Product/Attribute/Source/Price/ViewTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Model/Product/Attribute/Source/Price/ViewTest.php
index 5220ab8755d063684eb7394d680587f5a0f6ccce..7d560eda3678d1b24410882df967bf749013fdc3 100644
--- a/dev/tests/unit/testsuite/Magento/Bundle/Model/Product/Attribute/Source/Price/ViewTest.php
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Model/Product/Attribute/Source/Price/ViewTest.php
@@ -30,39 +30,98 @@ class ViewTest extends \PHPUnit_Framework_TestCase
     /**
      * @var \Magento\Bundle\Model\Product\Attribute\Source\Price\View
      */
-    protected $_model;
+    protected $model;
+
+    /**
+     * @var \Magento\Eav\Model\Resource\Entity\Attribute\Option|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $option;
+
+    /**
+     * @var \Magento\Eav\Model\Resource\Entity\Attribute\OptionFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $optionFactory;
+
+    /**
+     * @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $attribute;
 
     public function setUp()
     {
-        $objectManager = new ObjectManager($this);
-        $this->_model = $objectManager->getObject('Magento\Bundle\Model\Product\Attribute\Source\Price\View');
+        $this->option = $this->getMock('Magento\Eav\Model\Resource\Entity\Attribute\Option', [], [], '', false);
+        $this->optionFactory = $this->getMock('Magento\Eav\Model\Resource\Entity\Attribute\OptionFactory', ['create']);
+        $this->optionFactory->expects($this->any())->method('create')->will($this->returnValue($this->option));
+        $this->attribute = $this->getMock('Magento\Eav\Model\Entity\Attribute\AbstractAttribute', [], [], '', false);
+
+        $this->model = (new ObjectManager($this))
+            ->getObject('Magento\Bundle\Model\Product\Attribute\Source\Price\View', [
+                'optionFactory' => $this->optionFactory,
+            ]);
+        $this->model->setAttribute($this->attribute);
+    }
+
+    public function testGetAllOptions()
+    {
+        $options = $this->model->getAllOptions();
+
+        $this->assertInternalType('array', $options);
+        $this->assertNotEmpty($options);
+
+        foreach ($options as $option) {
+            $this->assertArrayHasKey('label', $option);
+            $this->assertArrayHasKey('value', $option);
+        }
+    }
+
+    /**
+     * @covers \Magento\Bundle\Model\Product\Attribute\Source\Price\View::getOptionText
+     */
+    public function testGetOptionTextForExistLabel()
+    {
+        $existValue = 1;
+
+        $this->assertInternalType('string', $this->model->getOptionText($existValue));
+    }
+
+    /**
+     * @covers \Magento\Bundle\Model\Product\Attribute\Source\Price\View::getOptionText
+     */
+    public function testGetOptionTextForNotExistLabel()
+    {
+        $notExistValue = -1;
+
+        $this->assertFalse($this->model->getOptionText($notExistValue));
     }
 
-    public function testGetFlatColums()
+    public function testGetFlatColumns()
     {
-        $abstractAttributeMock = $this->getMock(
-            '\Magento\Eav\Model\Entity\Attribute\AbstractAttribute',
-            array('getAttributeCode', '__wakeup'),
-            array(),
-            '',
-            false
-        );
-
-        $abstractAttributeMock->expects($this->any())->method('getAttributeCode')->will($this->returnValue('code'));
-
-        $this->_model->setAttribute($abstractAttributeMock);
-
-        $flatColums = $this->_model->getFlatColums();
-
-        $this->assertTrue(is_array($flatColums), 'FlatColums must be an array value');
-        $this->assertTrue(!empty($flatColums), 'FlatColums must be not empty');
-        foreach ($flatColums as $result) {
-            $this->assertArrayHasKey('unsigned', $result, 'FlatColums must have "unsigned" column');
-            $this->assertArrayHasKey('default', $result, 'FlatColums must have "default" column');
-            $this->assertArrayHasKey('extra', $result, 'FlatColums must have "extra" column');
-            $this->assertArrayHasKey('type', $result, 'FlatColums must have "type" column');
-            $this->assertArrayHasKey('nullable', $result, 'FlatColums must have "nullable" column');
-            $this->assertArrayHasKey('comment', $result, 'FlatColums must have "comment" column');
+        $code = 'attribute-code';
+        $this->attribute->expects($this->any())->method('getAttributeCode')->will($this->returnValue($code));
+
+        $columns = $this->model->getFlatColumns();
+
+        $this->assertInternalType('array', $columns);
+        $this->assertArrayHasKey($code, $columns);
+
+        foreach ($columns as $column) {
+            $this->assertArrayHasKey('unsigned', $column);
+            $this->assertArrayHasKey('default', $column);
+            $this->assertArrayHasKey('extra', $column);
+            $this->assertArrayHasKey('type', $column);
+            $this->assertArrayHasKey('nullable', $column);
+            $this->assertArrayHasKey('comment', $column);
         }
     }
+
+    public function testGetFlatUpdateSelect()
+    {
+        $store = 1;
+        $select = 'select';
+
+        $this->option->expects($this->once())->method('getFlatUpdateSelect')->with($this->attribute, $store, false)
+            ->will($this->returnValue($select));
+
+        $this->assertEquals($select, $this->model->getFlatUpdateSelect($store));
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Model/Sales/Order/Pdf/Items/AbstractItemsTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Model/Sales/Order/Pdf/Items/AbstractItemsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..703601a015bf4c62435cad4d0cbe0026632d612c
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Model/Sales/Order/Pdf/Items/AbstractItemsTest.php
@@ -0,0 +1,283 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Model\Sales\Order\Pdf\Items;
+
+class AbstractItemsTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Sales\Model\Order\Item|\PHPUnit_Framework_MockObject_MockObject */
+    protected $orderItem;
+
+    /** @var \Magento\Bundle\Model\Sales\Order\Pdf\Items\Shipment $model */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->orderItem = $this->getMock(
+            'Magento\Sales\Model\Order\Item',
+            ['getProductOptions', '__wakeup', 'getParentItem', 'getOrderItem', 'getOrderItemId', 'getId'],
+            [],
+            '',
+            false
+        );
+
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->model = $objectManager->getObject('Magento\Bundle\Model\Sales\Order\Pdf\Items\Shipment');
+    }
+
+    /**
+     * @dataProvider getChildrenEmptyItemsDataProvider
+     */
+    public function testGetChildrenEmptyItems($class, $method, $returnClass)
+    {
+        $salesModel = $this->getMock($returnClass, ['getAllItems', '__wakeup'], [], '', false);
+        $salesModel->expects($this->once())->method('getAllItems')->will($this->returnValue([]));
+
+        $item = $this->getMock($class, [$method, 'getOrderItem', '__wakeup'], [], '', false);
+        $item->expects($this->once())->method($method)->will($this->returnValue($salesModel));
+        $item->expects($this->once())->method('getOrderItem')->will($this->returnValue($this->orderItem));
+        $this->orderItem->expects($this->any())->method('getId')->will($this->returnValue(1));
+
+        $this->assertSame(null, $this->model->getChilds($item));
+    }
+
+    public function getChildrenEmptyItemsDataProvider()
+    {
+        return [
+            ['Magento\Sales\Model\Order\Invoice\Item', 'getInvoice', 'Magento\Sales\Model\Order\Invoice'],
+            ['Magento\Sales\Model\Order\Shipment\Item', 'getShipment', 'Magento\Sales\Model\Order\Shipment'],
+            ['Magento\Sales\Model\Order\Creditmemo\Item', 'getCreditmemo', 'Magento\Sales\Model\Order\Creditmemo']
+        ];
+    }
+
+    /**
+     * @dataProvider getChildrenDataProvider
+     */
+    public function testGetChildren($parentItem)
+    {
+        if ($parentItem) {
+            $parentItem = $this->getMock('Magento\Sales\Model\Order\Item', ['getId', '__wakeup'], [], '', false);
+            $parentItem->expects($this->any())->method('getId')->will($this->returnValue(1));
+        }
+        $this->orderItem->expects($this->any())->method('getOrderItem')->will($this->returnSelf());
+        $this->orderItem->expects($this->any())->method('getParentItem')->will($this->returnValue($parentItem));
+        $this->orderItem->expects($this->any())->method('getOrderItemId')->will($this->returnValue(2));
+        $this->orderItem->expects($this->any())->method('getId')->will($this->returnValue(1));
+
+        $salesModel = $this->getMock('Magento\Sales\Model\Order\Invoice', ['getAllItems', '__wakeup'], [], '', false);
+        $salesModel->expects($this->once())->method('getAllItems')->will($this->returnValue([$this->orderItem]));
+
+        $item = $this->getMock(
+            'Magento\Sales\Model\Order\Invoice\Item',
+            ['getInvoice', 'getOrderItem', '__wakeup'],
+            [],
+            '',
+            false
+        );
+        $item->expects($this->once())->method('getInvoice')->will($this->returnValue($salesModel));
+        $item->expects($this->any())->method('getOrderItem')->will($this->returnValue($this->orderItem));
+
+        $this->assertSame([2 => $this->orderItem], $this->model->getChilds($item));
+    }
+
+    public function getChildrenDataProvider()
+    {
+        return [
+            [true],
+            [false],
+        ];
+    }
+
+    /**
+     * @dataProvider isShipmentSeparatelyWithoutItemDataProvider
+     */
+    public function testIsShipmentSeparatelyWithoutItem($productOptions, $result)
+    {
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+
+        $this->assertSame($result, $this->model->isShipmentSeparately());
+    }
+
+    public function isShipmentSeparatelyWithoutItemDataProvider()
+    {
+        return [
+            [['shipment_type' => 1], true],
+            [['shipment_type' => 0], false],
+            [[], false]
+        ];
+    }
+
+    /**
+     * @dataProvider isShipmentSeparatelyWithItemDataProvider
+     */
+    public function testIsShipmentSeparatelyWithItem($productOptions, $result, $parentItem)
+    {
+        if ($parentItem) {
+            $parentItem =
+                $this->getMock('Magento\Sales\Model\Order\Item', ['getProductOptions', '__wakeup'], [], '', false);
+            $parentItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        } else {
+            $this->orderItem->expects($this->any())->method('getProductOptions')
+                ->will($this->returnValue($productOptions));
+        }
+        $this->orderItem->expects($this->any())->method('getParentItem')->will($this->returnValue($parentItem));
+        $this->orderItem->expects($this->any())->method('getOrderItem')->will($this->returnSelf());
+
+        $this->assertSame($result, $this->model->isShipmentSeparately($this->orderItem));
+    }
+
+    public function isShipmentSeparatelyWithItemDataProvider()
+    {
+        return [
+            [['shipment_type' => 1], false, false],
+            [['shipment_type' => 0], true, false],
+            [['shipment_type' => 1], true, true],
+            [['shipment_type' => 0], false, true],
+        ];
+    }
+
+    /**
+     * @dataProvider isChildCalculatedWithoutItemDataProvider
+     */
+    public function testIsChildCalculatedWithoutItem($productOptions, $result)
+    {
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+
+        $this->assertSame($result, $this->model->isChildCalculated());
+    }
+
+    public function isChildCalculatedWithoutItemDataProvider()
+    {
+        return [
+            [['product_calculations' => 0], true],
+            [['product_calculations' => 1], false],
+            [[], false],
+        ];
+    }
+
+    /**
+     * @dataProvider isChildCalculatedWithItemDataProvider
+     */
+    public function testIsChildCalculatedWithItem($productOptions, $result, $parentItem)
+    {
+        if ($parentItem) {
+            $parentItem =
+                $this->getMock('Magento\Sales\Model\Order\Item', ['getProductOptions', '__wakeup'], [], '', false);
+            $parentItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        } else {
+            $this->orderItem->expects($this->any())->method('getProductOptions')
+                ->will($this->returnValue($productOptions));
+        }
+        $this->orderItem->expects($this->any())->method('getParentItem')->will($this->returnValue($parentItem));
+        $this->orderItem->expects($this->any())->method('getOrderItem')->will($this->returnSelf());
+
+        $this->assertSame($result, $this->model->isChildCalculated($this->orderItem));
+    }
+
+    public function isChildCalculatedWithItemDataProvider()
+    {
+        return [
+            [['product_calculations' => 0], false, false],
+            [['product_calculations' => 1], true, false],
+            [['product_calculations' => 0], true, true],
+            [['product_calculations' => 1], false, true],
+        ];
+    }
+
+    /**
+     * @dataProvider getBundleOptionsDataProvider
+     */
+    public function testGetBundleOptions($productOptions, $result)
+    {
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        $this->assertSame($result, $this->model->getBundleOptions());
+    }
+
+    public function getBundleOptionsDataProvider()
+    {
+        return [
+            [['bundle_options' => 'result'], 'result'],
+            [[], []],
+        ];
+    }
+
+    /**
+     * @dataProvider getSelectionAttributesDataProvider
+     */
+    public function testGetSelectionAttributes($productOptions, $result)
+    {
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        $this->assertSame($result, $this->model->getSelectionAttributes($this->orderItem));
+    }
+
+    public function getSelectionAttributesDataProvider()
+    {
+        return [
+            [[], null],
+            [['bundle_selection_attributes' => 'a:1:{i:0;i:1;}'], [0 => 1]],
+        ];
+    }
+
+    public function testGetOrderOptions()
+    {
+        $productOptions = [
+            'options' => ['options'],
+            'additional_options' => ['additional_options'],
+            'attributes_info' => ['attributes_info']
+        ];
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+        $this->assertEquals(['attributes_info', 'options', 'additional_options'], $this->model->getOrderOptions());
+    }
+
+    public function testGetOrderItem()
+    {
+        $this->model->setItem($this->orderItem);
+        $this->assertSame($this->orderItem, $this->model->getOrderItem());
+    }
+
+    /**
+     * @dataProvider canShowPriceInfoDataProvider
+     */
+    public function testCanShowPriceInfo($parentItem, $productOptions, $result)
+    {
+        $this->model->setItem($this->orderItem);
+        $this->orderItem->expects($this->any())->method('getOrderItem')->will($this->returnSelf());
+        $this->orderItem->expects($this->any())->method('getParentItem')->will($this->returnValue($parentItem));
+        $this->orderItem->expects($this->any())->method('getProductOptions')->will($this->returnValue($productOptions));
+
+        $this->assertSame($result, $this->model->canShowPriceInfo($this->orderItem));
+    }
+
+    public function canShowPriceInfoDataProvider()
+    {
+        return [
+            [true, ['product_calculations' => 0], true],
+            [false, [], true],
+            [false, ['product_calculations' => 0], false],
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Service/V1/Product/Link/ReadServiceTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Service/V1/Product/Link/ReadServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2f262ccd0ac3e7234658da5bac5dbc7eb10e8a5c
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Service/V1/Product/Link/ReadServiceTest.php
@@ -0,0 +1,194 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Bundle\Service\V1\Product\Link;
+
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class ReadServiceTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Bundle\Service\V1\Product\Link\ReadService
+     */
+    private $model;
+
+    /**
+     * @var \Magento\Catalog\Model\ProductRepository|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productRepository;
+
+    /**
+     * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $product;
+
+    /**
+     * @var \Magento\Bundle\Service\V1\Data\Product\Link\MetadataConverter|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $metadataConverter;
+
+    /**
+     * @var \Magento\Bundle\Model\Product\Type\Interceptor|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productType;
+
+    /**
+     * @var \Magento\Bundle\Model\Resource\Option\Collection|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $optionCollection;
+
+    /**
+     * @var \Magento\Bundle\Model\Resource\Selection\Collection|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $selectionCollection;
+
+    /**
+     * @var \Magento\Bundle\Model\Option|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $option;
+
+    /**
+     * @var \Magento\Bundle\Service\V1\Data\Product\Link\Metadata|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $metadata;
+
+    private $storeId = 2;
+
+    private $optionIds = [1, 2, 3];
+
+    protected function setUp()
+    {
+        $helper = new ObjectManager($this);
+
+        $this->productRepository = $this->getMockBuilder('Magento\Catalog\Model\ProductRepository')
+            ->setMethods(['get'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->productType = $this->getMockBuilder('Magento\Bundle\Model\Product\Type\Interceptor')
+            ->setMethods(['getOptionsCollection', 'setStoreFilter', 'getSelectionsCollection', 'getOptionsIds'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->option = $this->getMockBuilder('Magento\Bundle\Model\Option')
+            ->setMethods(['getSelections', '__wakeup'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->optionCollection = $this->getMockBuilder('Magento\Bundle\Model\Resource\Option\Collection')
+            ->setMethods(['appendSelections'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->selectionCollection = $this->getMockBuilder('Magento\Bundle\Model\Resource\Selection\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->product = $this->getMockBuilder('Magento\Catalog\Model\Product')
+            ->setMethods(['getTypeInstance', 'getStoreId', 'getTypeId', '__wakeup'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->metadata = $this->getMockBuilder('Magento\Bundle\Service\V1\Data\Product\Link\Metadata')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->metadataConverter = $this->getMockBuilder(
+            'Magento\Bundle\Service\V1\Data\Product\Link\MetadataConverter'
+        )
+            ->setMethods(['createDataFromModel'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->model = $helper->getObject(
+            'Magento\Bundle\Service\V1\Product\Link\ReadService',
+            [
+                'productRepository' => $this->productRepository,
+                'metadataConverter' => $this->metadataConverter
+            ]
+        );
+    }
+
+    public function testGetChildren()
+    {
+        $productSku = 'productSku';
+
+        $this->getOptions();
+
+        $this->productRepository->expects($this->any())->method('get')->with($this->equalTo($productSku))
+            ->will($this->returnValue($this->product));
+
+        $this->product->expects($this->once())->method('getTypeId')->will($this->returnValue('bundle'));
+
+        $this->productType->expects($this->once())->method('setStoreFilter')->with(
+            $this->equalTo($this->storeId),
+            $this->product
+        );
+        $this->productType->expects($this->once())->method('getSelectionsCollection')
+            ->with($this->equalTo($this->optionIds), $this->equalTo($this->product))
+            ->will($this->returnValue($this->selectionCollection));
+        $this->productType->expects($this->once())->method('getOptionsIds')->with($this->equalTo($this->product))
+            ->will($this->returnValue($this->optionIds));
+
+        $this->optionCollection->expects($this->once())->method('appendSelections')
+            ->with($this->equalTo($this->selectionCollection))
+            ->will($this->returnValue([$this->option]));
+
+        $this->option->expects($this->any())->method('getSelections')->will($this->returnValue([$this->product]));
+
+        $this->metadataConverter->expects($this->once())->method('createDataFromModel')
+            ->with($this->equalTo($this->product), $this->equalTo($this->product))
+            ->will($this->returnValue($this->metadata));
+
+        $this->assertEquals([$this->metadata], $this->model->getChildren($productSku));
+    }
+
+    /**
+     * @expectedException \Magento\Webapi\Exception
+     * @expectedExceptionCode 403
+     */
+    public function testGetChildrenException()
+    {
+        $productSku = 'productSku';
+
+        $this->productRepository->expects($this->once())->method('get')->with($this->equalTo($productSku))
+            ->will($this->returnValue($this->product));
+
+        $this->product->expects($this->once())->method('getTypeId')->will($this->returnValue('simple'));
+
+        $this->assertEquals([$this->metadata], $this->model->getChildren($productSku));
+    }
+
+    private function getOptions()
+    {
+        $this->product->expects($this->once())->method('getStoreId')->will($this->returnValue($this->storeId));
+        $this->product->expects($this->any())->method('getTypeInstance')->will($this->returnValue($this->productType));
+
+        $this->productType->expects($this->once())->method('setStoreFilter')
+            ->with($this->equalTo($this->storeId), $this->equalTo($this->product));
+        $this->productType->expects($this->once())->method('getOptionsCollection')
+            ->with($this->equalTo($this->product))
+            ->will($this->returnValue($this->optionCollection));
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Service/V1/Product/Link/WriteServiceTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Service/V1/Product/Link/WriteServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..58dcca446fcb9496cdde0b302aff52b3a4e607c2
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Service/V1/Product/Link/WriteServiceTest.php
@@ -0,0 +1,626 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Bundle\Service\V1\Product\Link;
+
+class WriteServiceTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var WriteService
+     */
+    protected $service;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Catalog\Model\ProductRepository
+     */
+    protected $productRepositoryMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Bundle\Model\SelectionFactory
+     */
+    protected $bundleSelectionMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Bundle\Model\Resource\BundleFactory
+     */
+    protected $bundleFactoryMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Bundle\Model\Resource\Option\CollectionFactory
+     */
+    protected $optionCollectionFactoryMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Store\Model\StoreManagerInterface
+     */
+    protected $storeManagerMock;
+
+    /**
+     * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $product;
+
+    /**
+     * @var \Magento\Bundle\Model\Product\Type\Interceptor|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productType;
+
+    /**
+     * @var \Magento\Bundle\Model\Resource\Option\Collection|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $optionCollection;
+
+    /**
+     * @var \Magento\Bundle\Model\Option|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $option;
+
+    protected function setUp()
+    {
+        $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
+
+        $this->productRepositoryMock = $this->getMock(
+            '\Magento\Catalog\Model\ProductRepository', array(), array(), '', false
+        );
+
+        $this->bundleSelectionMock = $this->getMock(
+            '\Magento\Bundle\Model\SelectionFactory', array('create'), array(), '', false
+        );
+
+        $this->bundleFactoryMock = $this->getMock(
+            '\Magento\Bundle\Model\Resource\BundleFactory', array('create'), array(), '', false
+        );
+
+        $this->optionCollectionFactoryMock = $this->getMock(
+            '\Magento\Bundle\Model\Resource\Option\CollectionFactory', array('create'), array(), '', false
+        );
+
+        $this->storeManagerMock = $this->getMock(
+            '\Magento\Store\Model\StoreManagerInterface', array(), array(), '', false
+        );
+
+        $this->product = $this->getMockBuilder('Magento\Catalog\Model\Product')
+            ->setMethods(['getTypeInstance', 'getStoreId', 'getTypeId', 'getId', '__wakeup'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->productType = $this->getMockBuilder('Magento\Bundle\Model\Product\Type\Interceptor')
+            ->setMethods(['getOptionsCollection', 'setStoreFilter', 'getSelectionsCollection', 'getOptionsIds'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->option = $this->getMockBuilder('Magento\Bundle\Model\Option')
+            ->setMethods(['getSelections', '__wakeup'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->optionCollection = $this->getMockBuilder('Magento\Bundle\Model\Resource\Option\Collection')
+            ->setMethods(['appendSelections'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->service = $helper->getObject('Magento\Bundle\Service\V1\Product\Link\WriteService',
+            [
+                'productRepository' => $this->productRepositoryMock,
+                'bundleSelection' => $this->bundleSelectionMock,
+                'bundleFactory' => $this->bundleFactoryMock,
+                'optionCollection' => $this->optionCollectionFactoryMock,
+                'storeManager' => $this->storeManagerMock
+            ]
+        );
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\InputException
+     */
+    public function testAddChildToNotBundleProduct()
+    {
+        $productLink = $this->getMock(
+            'Magento\Bundle\Service\V1\Product\Link\Data\ProductLink', array(), array(), '', false
+        );
+
+        $productMock = $this->getMock('\Magento\Catalog\Model\Product', array(), array(), '', false);
+        $productMock->expects($this->once())->method('getTypeId')->will($this->returnValue(
+            \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE
+        ));
+        $this->productRepositoryMock
+            ->expects($this->once())
+            ->method('get')
+            ->with('product_sku')
+            ->will($this->returnValue($productMock));
+        $this->service->addChild('product_sku', 1, $productLink);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\InputException
+     */
+    public function testAddChildNonExistingOption()
+    {
+        $productLink = $this->getMock(
+            'Magento\Bundle\Service\V1\Product\Link\Data\ProductLink', array(), array(), '', false
+        );
+
+        $productMock = $this->getMock('\Magento\Catalog\Model\Product', array(), array(), '', false);
+        $productMock->expects($this->once())->method('getTypeId')->will($this->returnValue(
+            \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE
+        ));
+        $productMock->expects($this->once())->method('getId')->will($this->returnValue('product_id'));
+        $this->productRepositoryMock
+            ->expects($this->once())
+            ->method('get')
+            ->with('product_sku')
+            ->will($this->returnValue($productMock));
+
+        $store = $this->getMock('\Magento\Store\Model\Store', array(), array(), '', false);
+        $this->storeManagerMock->expects($this->any())->method('getStore')->will($this->returnValue($store));
+        $store->expects($this->any())->method('getId')->will($this->returnValue(0));
+
+        $option = $this->getMockBuilder('\Magento\Bundle\Model\Option')->disableOriginalConstructor()
+            ->setMethods(['getOptionId', '__wakeup'])
+            ->getMock();
+        $option->expects($this->once())->method('getOptionId')->will($this->returnValue(2));
+
+        $optionsCollectionMock = $this->getMock(
+            '\Magento\Bundle\Model\Resource\Option\Collection', array(), array(), '', false
+        );
+        $optionsCollectionMock->expects($this->once())
+            ->method('setProductIdFilter')
+            ->with($this->equalTo('product_id'))
+            ->will($this->returnSelf());
+        $optionsCollectionMock->expects($this->once())
+            ->method('joinValues')
+            ->with($this->equalTo(0))
+            ->will($this->returnSelf());
+        $optionsCollectionMock->expects($this->any())->method('getIterator')->will(
+            $this->returnValue(new \ArrayIterator([$option]))
+        );
+        $this->optionCollectionFactoryMock->expects($this->any())->method('create')->will(
+            $this->returnValue($optionsCollectionMock)
+        );
+        $this->service->addChild('product_sku', 1, $productLink);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\InputException
+     * @expectedExceptionMessage Bundle product could not contain another composite product
+     */
+    public function testAddChildLinkedProductIsComposite()
+    {
+        $productLink = $this->getMock(
+            'Magento\Bundle\Service\V1\Product\Link\Data\ProductLink', array(), array(), '', false
+        );
+        $productLink->expects($this->any())->method('getSku')->will($this->returnValue('linked_product_sku'));
+
+        $productMock = $this->getMock('\Magento\Catalog\Model\Product', array(), array(), '', false);
+        $productMock->expects($this->once())->method('getTypeId')->will($this->returnValue(
+            \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE
+        ));
+        $productMock->expects($this->any())->method('getId')->will($this->returnValue('product_id'));
+
+        $linkedProductMock = $this->getMock('\Magento\Catalog\Model\Product', array(), array(), '', false);
+        $linkedProductMock->expects($this->any())->method('getId')->will($this->returnValue(13));
+        $linkedProductMock->expects($this->once())->method('isComposite')->will($this->returnValue(true));
+        $this->productRepositoryMock
+            ->expects($this->at(0))
+            ->method('get')
+            ->with('product_sku')
+            ->will($this->returnValue($productMock));
+        $this->productRepositoryMock
+            ->expects($this->at(1))
+            ->method('get')
+            ->with('linked_product_sku')
+            ->will($this->returnValue($linkedProductMock));
+
+        $store = $this->getMock('\Magento\Store\Model\Store', array(), array(), '', false);
+        $this->storeManagerMock->expects($this->any())->method('getStore')->will($this->returnValue($store));
+        $store->expects($this->any())->method('getId')->will($this->returnValue(0));
+
+        $option = $this->getMockBuilder('\Magento\Bundle\Model\Option')->disableOriginalConstructor()
+            ->setMethods(['getOptionId', '__wakeup'])
+            ->getMock();
+        $option->expects($this->once())->method('getOptionId')->will($this->returnValue(1));
+
+        $optionsCollectionMock = $this->getMock(
+            '\Magento\Bundle\Model\Resource\Option\Collection', array(), array(), '', false
+        );
+        $optionsCollectionMock->expects($this->once())
+            ->method('setProductIdFilter')
+            ->with($this->equalTo('product_id'))
+            ->will($this->returnSelf());
+        $optionsCollectionMock->expects($this->once())
+            ->method('joinValues')
+            ->with($this->equalTo(0))
+            ->will($this->returnSelf());
+        $optionsCollectionMock->expects($this->any())->method('getIterator')->will(
+            $this->returnValue(new \ArrayIterator([$option]))
+        );
+        $this->optionCollectionFactoryMock->expects($this->any())->method('create')->will(
+            $this->returnValue($optionsCollectionMock)
+        );
+
+        $bundle = $this->getMock('\Magento\Bundle\Model\Resource\Bundle', array(), array(), '', false);
+        $bundle->expects($this->once())->method('getSelectionsData')
+            ->with('product_id')
+            ->will($this->returnValue([]));
+        $this->bundleFactoryMock->expects($this->once())->method('create')->will($this->returnValue($bundle));
+
+        $this->service->addChild('product_sku', 1, $productLink);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\CouldNotSaveException
+     */
+    public function testAddChildProductAlreadyExistsInOption()
+    {
+        $productLink = $this->getMock(
+            'Magento\Bundle\Service\V1\Product\Link\Data\ProductLink', array(), array(), '', false
+        );
+        $productLink->expects($this->any())->method('getSku')->will($this->returnValue('linked_product_sku'));
+
+        $productMock = $this->getMock('\Magento\Catalog\Model\Product', array(), array(), '', false);
+        $productMock->expects($this->once())->method('getTypeId')->will($this->returnValue(
+            \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE
+        ));
+        $productMock->expects($this->any())->method('getId')->will($this->returnValue('product_id'));
+
+        $linkedProductMock = $this->getMock('\Magento\Catalog\Model\Product', array(), array(), '', false);
+        $linkedProductMock->expects($this->any())->method('getId')->will($this->returnValue(13));
+        $linkedProductMock->expects($this->once())->method('isComposite')->will($this->returnValue(false));
+        $this->productRepositoryMock
+            ->expects($this->at(0))
+            ->method('get')
+            ->with('product_sku')
+            ->will($this->returnValue($productMock));
+        $this->productRepositoryMock
+            ->expects($this->at(1))
+            ->method('get')
+            ->with('linked_product_sku')
+            ->will($this->returnValue($linkedProductMock));
+
+        $store = $this->getMock('\Magento\Store\Model\Store', array(), array(), '', false);
+        $this->storeManagerMock->expects($this->any())->method('getStore')->will($this->returnValue($store));
+        $store->expects($this->any())->method('getId')->will($this->returnValue(0));
+
+        $option = $this->getMockBuilder('\Magento\Bundle\Model\Option')->disableOriginalConstructor()
+            ->setMethods(['getOptionId', '__wakeup'])
+            ->getMock();
+        $option->expects($this->once())->method('getOptionId')->will($this->returnValue(1));
+
+        $optionsCollectionMock = $this->getMock(
+            '\Magento\Bundle\Model\Resource\Option\Collection', array(), array(), '', false
+        );
+        $optionsCollectionMock->expects($this->once())
+            ->method('setProductIdFilter')
+            ->with($this->equalTo('product_id'))
+            ->will($this->returnSelf());
+        $optionsCollectionMock->expects($this->once())
+            ->method('joinValues')
+            ->with($this->equalTo(0))
+            ->will($this->returnSelf());
+        $optionsCollectionMock->expects($this->any())->method('getIterator')->will(
+            $this->returnValue(new \ArrayIterator([$option]))
+        );
+        $this->optionCollectionFactoryMock->expects($this->any())->method('create')->will(
+            $this->returnValue($optionsCollectionMock)
+        );
+
+        $selections = [
+            ['option_id' => 1, 'product_id' => 12],
+            ['option_id' => 1, 'product_id' => 13],
+        ];
+        $bundle = $this->getMock('\Magento\Bundle\Model\Resource\Bundle', array(), array(), '', false);
+        $bundle->expects($this->once())->method('getSelectionsData')
+            ->with('product_id')
+            ->will($this->returnValue($selections));
+        $this->bundleFactoryMock->expects($this->once())->method('create')->will($this->returnValue($bundle));
+
+        $this->service->addChild('product_sku', 1, $productLink);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\CouldNotSaveException
+     */
+    public function testAddChildCouldNotSave()
+    {
+        $productLink = $this->getMock(
+            'Magento\Bundle\Service\V1\Product\Link\Data\ProductLink', array(), array(), '', false
+        );
+        $productLink->expects($this->any())->method('getSku')->will($this->returnValue('linked_product_sku'));
+
+        $productMock = $this->getMock('\Magento\Catalog\Model\Product', array(), array(), '', false);
+        $productMock->expects($this->once())->method('getTypeId')->will($this->returnValue(
+            \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE
+        ));
+        $productMock->expects($this->any())->method('getId')->will($this->returnValue('product_id'));
+
+        $linkedProductMock = $this->getMock('\Magento\Catalog\Model\Product', array(), array(), '', false);
+        $linkedProductMock->expects($this->any())->method('getId')->will($this->returnValue(13));
+        $linkedProductMock->expects($this->once())->method('isComposite')->will($this->returnValue(false));
+        $this->productRepositoryMock
+            ->expects($this->at(0))
+            ->method('get')
+            ->with('product_sku')
+            ->will($this->returnValue($productMock));
+        $this->productRepositoryMock
+            ->expects($this->at(1))
+            ->method('get')
+            ->with('linked_product_sku')
+            ->will($this->returnValue($linkedProductMock));
+
+        $store = $this->getMock('\Magento\Store\Model\Store', array(), array(), '', false);
+        $this->storeManagerMock->expects($this->any())->method('getStore')->will($this->returnValue($store));
+        $store->expects($this->any())->method('getId')->will($this->returnValue(0));
+
+        $option = $this->getMockBuilder('\Magento\Bundle\Model\Option')->disableOriginalConstructor()
+            ->setMethods(['getOptionId', '__wakeup'])
+            ->getMock();
+        $option->expects($this->once())->method('getOptionId')->will($this->returnValue(1));
+
+        $optionsCollectionMock = $this->getMock(
+            '\Magento\Bundle\Model\Resource\Option\Collection', array(), array(), '', false
+        );
+        $optionsCollectionMock->expects($this->once())
+            ->method('setProductIdFilter')
+            ->with($this->equalTo('product_id'))
+            ->will($this->returnSelf());
+        $optionsCollectionMock->expects($this->once())
+            ->method('joinValues')
+            ->with($this->equalTo(0))
+            ->will($this->returnSelf());
+        $optionsCollectionMock->expects($this->any())->method('getIterator')->will(
+            $this->returnValue(new \ArrayIterator([$option]))
+        );
+        $this->optionCollectionFactoryMock->expects($this->any())->method('create')->will(
+            $this->returnValue($optionsCollectionMock)
+        );
+
+        $selections = [
+            ['option_id' => 1, 'product_id' => 11],
+            ['option_id' => 1, 'product_id' => 12],
+        ];
+        $bundle = $this->getMock('\Magento\Bundle\Model\Resource\Bundle', array(), array(), '', false);
+        $bundle->expects($this->once())->method('getSelectionsData')
+            ->with('product_id')
+            ->will($this->returnValue($selections));
+        $this->bundleFactoryMock->expects($this->once())->method('create')->will($this->returnValue($bundle));
+
+        $selection = $this->getMock('\Magento\Framework\Object', array('save'), array(), '', false);
+        $selection->expects($this->once())->method('save')
+            ->will(
+                $this->returnCallback(
+                    function () {
+                        throw new \Exception('message');
+                    }
+                )
+            );
+        $this->bundleSelectionMock->expects($this->once())->method('create')->will($this->returnValue($selection));
+        $this->service->addChild('product_sku', 1, $productLink);
+    }
+
+    public function testAddChild()
+    {
+        $productLink = $this->getMock(
+            'Magento\Bundle\Service\V1\Product\Link\Data\ProductLink', array(), array(), '', false
+        );
+        $productLink->expects($this->any())->method('getSku')->will($this->returnValue('linked_product_sku'));
+
+        $productMock = $this->getMock('\Magento\Catalog\Model\Product', array(), array(), '', false);
+        $productMock->expects($this->once())->method('getTypeId')->will($this->returnValue(
+            \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE
+        ));
+        $productMock->expects($this->any())->method('getId')->will($this->returnValue('product_id'));
+
+        $linkedProductMock = $this->getMock('\Magento\Catalog\Model\Product', array(), array(), '', false);
+        $linkedProductMock->expects($this->any())->method('getId')->will($this->returnValue(13));
+        $linkedProductMock->expects($this->once())->method('isComposite')->will($this->returnValue(false));
+        $this->productRepositoryMock
+            ->expects($this->at(0))
+            ->method('get')
+            ->with('product_sku')
+            ->will($this->returnValue($productMock));
+        $this->productRepositoryMock
+            ->expects($this->at(1))
+            ->method('get')
+            ->with('linked_product_sku')
+            ->will($this->returnValue($linkedProductMock));
+
+        $store = $this->getMock('\Magento\Store\Model\Store', array(), array(), '', false);
+        $this->storeManagerMock->expects($this->any())->method('getStore')->will($this->returnValue($store));
+        $store->expects($this->any())->method('getId')->will($this->returnValue(0));
+
+        $option = $this->getMockBuilder('\Magento\Bundle\Model\Option')->disableOriginalConstructor()
+            ->setMethods(['getOptionId', '__wakeup'])
+            ->getMock();
+        $option->expects($this->once())->method('getOptionId')->will($this->returnValue(1));
+
+        $optionsCollectionMock = $this->getMock(
+            '\Magento\Bundle\Model\Resource\Option\Collection', array(), array(), '', false
+        );
+        $optionsCollectionMock->expects($this->once())
+            ->method('setProductIdFilter')
+            ->with($this->equalTo('product_id'))
+            ->will($this->returnSelf());
+        $optionsCollectionMock->expects($this->once())
+            ->method('joinValues')
+            ->with($this->equalTo(0))
+            ->will($this->returnSelf());
+        $optionsCollectionMock->expects($this->any())->method('getIterator')->will(
+            $this->returnValue(new \ArrayIterator([$option]))
+        );
+        $this->optionCollectionFactoryMock->expects($this->any())->method('create')->will(
+            $this->returnValue($optionsCollectionMock)
+        );
+
+        $selections = [
+            ['option_id' => 1, 'product_id' => 11],
+            ['option_id' => 1, 'product_id' => 12],
+        ];
+        $bundle = $this->getMock('\Magento\Bundle\Model\Resource\Bundle', array(), array(), '', false);
+        $bundle->expects($this->once())->method('getSelectionsData')
+            ->with('product_id')
+            ->will($this->returnValue($selections));
+        $this->bundleFactoryMock->expects($this->once())->method('create')->will($this->returnValue($bundle));
+
+        $selection = $this->getMock('\Magento\Framework\Object', array('save', 'getId'), array(), '', false);
+        $selection->expects($this->once())->method('save');
+        $selection->expects($this->once())->method('getId')->will($this->returnValue(42));
+        $this->bundleSelectionMock->expects($this->once())->method('create')->will($this->returnValue($selection));
+        $result = $this->service->addChild('product_sku', 1, $productLink);
+        $this->assertEquals(42, $result);
+    }
+
+
+    public function testRemoveChild()
+    {
+        $this->productRepositoryMock->expects($this->any())->method('get')->will($this->returnValue($this->product));
+        $bundle = $this->getMock('\Magento\Bundle\Model\Resource\Bundle', array(), array(), '', false);
+        $this->bundleFactoryMock->expects($this->once())->method('create')->will($this->returnValue($bundle));
+        $productSku = 'productSku';
+        $optionId = 1;
+        $childSku = 'childSku';
+
+        $this->product
+            ->expects($this->any())
+            ->method('getTypeId')
+            ->will($this->returnValue(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE));
+
+        $this->getOptions();
+
+        $selection = $this->getMockBuilder('\Magento\Bundle\Model\Selection')
+            ->setMethods(['getSku', 'getOptionId', 'getSelectionId', 'getProductId', '__wakeup'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $selection->expects($this->any())->method('getSku')->will($this->returnValue($childSku));
+        $selection->expects($this->any())->method('getOptionId')->will($this->returnValue($optionId));
+        $selection->expects($this->any())->method('getSelectionId')->will($this->returnValue(55));
+        $selection->expects($this->any())->method('getProductId')->will($this->returnValue(1));
+
+        $this->option->expects($this->any())->method('getSelections')->will($this->returnValue([$selection]));
+        $this->product->expects($this->any())->method('getId')->will($this->returnValue(3));
+
+        $bundle->expects($this->once())->method('dropAllUnneededSelections')->with(3, array());
+        $bundle->expects($this->once())->method('saveProductRelations')->with(3, array());
+        $this->assertTrue($this->service->removeChild($productSku, $optionId, $childSku));
+    }
+
+    /**
+     * @expectedException \Magento\Webapi\Exception
+     * @expectedExceptionCode 403
+     */
+    public function testRemoveChildForbidden()
+    {
+        $this->productRepositoryMock->expects($this->any())->method('get')->will($this->returnValue($this->product));
+        $productSku = 'productSku';
+        $optionId = 1;
+        $childSku = 'childSku';
+
+        $this->product
+            ->expects($this->any())
+            ->method('getTypeId')
+            ->will($this->returnValue(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE));
+
+        $this->service->removeChild($productSku, $optionId, $childSku);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function testRemoveChildInvalidOptionId()
+    {
+        $this->productRepositoryMock->expects($this->any())->method('get')->will($this->returnValue($this->product));
+        $productSku = 'productSku';
+        $optionId = 1;
+        $childSku = 'childSku';
+
+        $this->product
+            ->expects($this->any())
+            ->method('getTypeId')
+            ->will($this->returnValue(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE));
+
+        $this->getOptions();
+
+        $selection = $this->getMockBuilder('\Magento\Bundle\Model\Selection')
+            ->setMethods(['getSku', 'getOptionId', 'getSelectionId', 'getProductId', '__wakeup'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $selection->expects($this->any())->method('getSku')->will($this->returnValue($childSku));
+        $selection->expects($this->any())->method('getOptionId')->will($this->returnValue($optionId + 1));
+        $selection->expects($this->any())->method('getSelectionId')->will($this->returnValue(55));
+        $selection->expects($this->any())->method('getProductId')->will($this->returnValue(1));
+
+        $this->option->expects($this->any())->method('getSelections')->will($this->returnValue([$selection]));
+        $this->service->removeChild($productSku, $optionId, $childSku);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function testRemoveChildInvalidChildSku()
+    {
+        $this->productRepositoryMock->expects($this->any())->method('get')->will($this->returnValue($this->product));
+        $productSku = 'productSku';
+        $optionId = 1;
+        $childSku = 'childSku';
+
+        $this->product
+            ->expects($this->any())
+            ->method('getTypeId')
+            ->will($this->returnValue(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE));
+
+        $this->getOptions();
+
+        $selection = $this->getMockBuilder('\Magento\Bundle\Model\Selection')
+            ->setMethods(['getSku', 'getOptionId', 'getSelectionId', 'getProductId', '__wakeup'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $selection->expects($this->any())->method('getSku')->will($this->returnValue($childSku . '_invalid'));
+        $selection->expects($this->any())->method('getOptionId')->will($this->returnValue($optionId));
+        $selection->expects($this->any())->method('getSelectionId')->will($this->returnValue(55));
+        $selection->expects($this->any())->method('getProductId')->will($this->returnValue(1));
+
+        $this->option->expects($this->any())->method('getSelections')->will($this->returnValue([$selection]));
+        $this->service->removeChild($productSku, $optionId, $childSku);
+    }
+
+    public function getOptions()
+    {
+        $this->product->expects($this->any())->method('getTypeInstance')->will($this->returnValue($this->productType));
+        $this->product->expects($this->once())->method('getStoreId')->will($this->returnValue(1));
+
+        $this->productType->expects($this->once())->method('setStoreFilter');
+        $this->productType->expects($this->once())->method('getOptionsCollection')
+            ->with($this->equalTo($this->product))
+            ->will($this->returnValue($this->optionCollection));
+
+        $this->productType->expects($this->once())->method('getOptionsIds')->with($this->equalTo($this->product))
+            ->will($this->returnValue([1, 2, 3]));
+
+        $this->productType->expects($this->once())->method('getSelectionsCollection')
+            ->will($this->returnValue([]));
+
+        $this->optionCollection->expects($this->any())->method('appendSelections')
+            ->with($this->equalTo([]))
+            ->will($this->returnValue([$this->option]));
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/ActionTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/ActionTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b79481348a6413e3a9631cf520b5b5ac8e7ed55d
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/ActionTest.php
@@ -0,0 +1,233 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Product;
+
+class ActionTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Product\Action
+     */
+    protected $model;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $productWebsiteFactory;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $resource;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $productWebsite;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $indexIndexer;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $categoryIndexer;
+
+    /**
+     * @var \Magento\Eav\Model\Config|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $eavConfig;
+
+    /**
+     * @var \Magento\Catalog\Model\Resource\Eav\Attribute|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $eavAttribute;
+
+    public function setUp()
+    {
+        $eventManagerMock = $this->getMock('Magento\Framework\Event\ManagerInterface');
+        $this->productWebsiteFactory = $this->getMock(
+            '\Magento\Catalog\Model\Product\WebsiteFactory',
+            ['create'],
+            [],
+            '',
+            false
+        );
+        $this->resource = $this->getMock(
+            '\Magento\Framework\Model\Resource\AbstractResource',
+            ['updateAttributes', '_getWriteAdapter', '_getReadAdapter', '_construct', 'getIdFieldName'],
+            [],
+            '',
+            false
+        );
+        $this->productWebsite = $this->getMock(
+            '\Magento\Catalog\Model\Product\Website',
+            ['addProducts', 'removeProducts', '__wakeup'],
+            [],
+            '',
+            false
+        );
+        $this->productWebsiteFactory
+            ->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($this->productWebsite));
+        $this->indexIndexer = $this->getMock(
+            '\Magento\Index\Model\Indexer',
+            ['processEntityAction', '__wakeup'],
+            [],
+            '',
+            false
+        );
+        $this->categoryIndexer = $this->getMock(
+            '\Magento\Indexer\Model\Indexer',
+            ['getId', 'load', 'isScheduled', 'reindexList'],
+            [],
+            '',
+            false
+        );
+        $this->eavConfig = $this->getMock(
+            '\Magento\Eav\Model\Config',
+            ['__wakeup', 'getAttribute'],
+            [],
+            '',
+            false
+        );
+        $this->eavAttribute = $this->getMock(
+            '\Magento\Catalog\Model\Resource\Eav\Attribute',
+            ['__wakeup', 'isIndexable'],
+            [],
+            '',
+            false
+        );
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->model = $objectManager->getObject(
+            '\Magento\Catalog\Model\Product\Action',
+            [
+                'eventDispatcher' => $eventManagerMock,
+                'resource' => $this->resource,
+                'productWebsiteFactory' => $this->productWebsiteFactory,
+                'indexIndexer' => $this->indexIndexer,
+                'categoryIndexer' => $this->categoryIndexer,
+                'eavConfig' => $this->eavConfig
+            ]
+        );
+    }
+
+    public function testUpdateAttributes()
+    {
+        $productIds = [1, 2, 2, 4];
+        $productIdsUnique = [0 => 1, 1 => 2, 3 => 4];
+        $attrData = [1];
+        $storeId = 1;
+        $this->resource
+            ->expects($this->any())
+            ->method('updateAttributes')
+            ->with($productIds, $attrData, $storeId)
+            ->will($this->returnSelf());
+        $this->indexIndexer
+            ->expects($this->any())
+            ->method('processEntityAction')
+            ->with($this->model, 'catalog_product', 'mass_action');
+        $this->categoryIndexer
+            ->expects($this->any())
+            ->method('getId')
+            ->will($this->returnValue(false));
+        $this->categoryIndexer
+            ->expects($this->any())
+            ->method('load')
+            ->with('catalog_product_category')
+            ->will($this->returnSelf());
+        $this->categoryIndexer
+            ->expects($this->any())
+            ->method('isScheduled')
+            ->will($this->returnValue(false));
+        $this->categoryIndexer
+            ->expects($this->any())
+            ->method('reindexList')
+            ->will($this->returnValue($productIds));
+        $this->eavConfig
+            ->expects($this->any())
+            ->method('getAttribute')
+            ->will($this->returnValue($this->eavAttribute));
+        $this->eavAttribute
+            ->expects($this->any())
+            ->method('isIndexable')
+            ->will($this->returnValue(false));
+        $this->assertEquals($this->model, $this->model->updateAttributes($productIds, $attrData, $storeId));
+        $this->assertEquals($this->model->getDataByKey('product_ids'), $productIdsUnique);
+        $this->assertEquals($this->model->getDataByKey('attributes_data'), $attrData);
+        $this->assertEquals($this->model->getDataByKey('store_id'), $storeId);
+    }
+
+    /**
+     * @param $type
+     * @param $methodName
+     * @dataProvider updateWebsitesDataProvider
+     */
+    public function testUpdateWebsites($type, $methodName)
+    {
+        $productIds = [1, 2, 2, 4];
+        $productIdsUnique = [0 => 1, 1 => 2, 3 => 4];
+        $websiteIds = [1];
+        $this->productWebsite
+            ->expects($this->any())
+            ->method($methodName)
+            ->with($websiteIds, $productIds)
+            ->will($this->returnSelf());
+        $this->indexIndexer
+            ->expects($this->any())
+            ->method('processEntityAction')
+            ->with($this->model, 'catalog_product', 'mass_action');
+        $this->categoryIndexer
+            ->expects($this->any())
+            ->method('getId')
+            ->will($this->returnValue(false));
+        $this->categoryIndexer
+            ->expects($this->any())
+            ->method('load')
+            ->with('catalog_product_category')
+            ->will($this->returnSelf());
+        $this->categoryIndexer
+            ->expects($this->any())
+            ->method('isScheduled')
+            ->will($this->returnValue(false));
+        $this->categoryIndexer
+            ->expects($this->any())
+            ->method('reindexList')
+            ->will($this->returnValue($productIds));
+        $this->model->updateWebsites($productIds, $websiteIds, $type);
+        $this->assertEquals($this->model->getDataByKey('product_ids'), $productIdsUnique);
+        $this->assertEquals($this->model->getDataByKey('website_ids'), $websiteIds);
+        $this->assertEquals($this->model->getDataByKey('action_type'), $type);
+    }
+
+    public function updateWebsitesDataProvider()
+    {
+        return [
+            ['$type' => 'add', '$methodName' => 'addProducts'],
+            ['$type' => 'remove', '$methodName' => 'removeProducts']
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/MediaTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/MediaTest.php
index 821ab44fee3ac603e8590fdd061fddc5de8f8018..1250a1a6254f800f7c513ada2a77518eb28cfcff 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/MediaTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/MediaTest.php
@@ -75,7 +75,8 @@ class MediaTest extends \PHPUnit_Framework_TestCase
                 'insertGallery',
                 'deleteGalleryValueInStore',
                 'insertGalleryValueInStore',
-                'deleteGallery'
+                'deleteGallery',
+                'loadGallery'
             ],
             [],
             '',
@@ -113,7 +114,7 @@ class MediaTest extends \PHPUnit_Framework_TestCase
         );
         $this->dataObject = $this->getMockBuilder('Magento\Framework\Object')
             ->disableOriginalConstructor()
-            ->setMethods(['getIsDuplicate', 'isLockedAttribute'])
+            ->setMethods(['getIsDuplicate', 'isLockedAttribute', 'getMediaAttributes'])
             ->getMock();
     }
 
@@ -123,7 +124,7 @@ class MediaTest extends \PHPUnit_Framework_TestCase
         $attributeId = 345345;
 
         $attribute = $this->getMock(
-            'Magento\Eav\Model\Entity\Attribute\AbstractAttribute',
+            'Magento\Eav\Model\Entity\Attribute',
             ['getBackendTable', 'isStatic', 'getAttributeId', 'getName', '__wakeup'],
             [],
             '',
@@ -259,4 +260,163 @@ class MediaTest extends \PHPUnit_Framework_TestCase
         $this->model->setAttribute($attributeMock);
         $this->assertNull($this->model->afterSave($this->dataObject));
     }
+
+    /**
+     * @dataProvider afterLoadDataProvider
+     * @param array $image
+     */
+    public function testAfterLoad($image)
+    {
+        $attributeCode = 'attr_code';
+        $attribute = $this->getMock(
+            'Magento\Eav\Model\Entity\Attribute',
+            ['getAttributeCode', '__wakeup'],
+            [],
+            '',
+            false
+        );
+        $attribute->expects($this->any())->method('getAttributeCode')->will($this->returnValue($attributeCode));
+        $this->resourceModel->expects($this->any())->method('loadGallery')->will($this->returnValue([$image]));
+
+        $this->model->setAttribute($attribute);
+        $this->model->afterLoad($this->dataObject);
+        $this->assertEquals([$image], $this->dataObject->getAttrCode('images'));
+    }
+
+    public function afterLoadDataProvider()
+    {
+        return [
+            [
+                [
+                    'label' => 'label_1',
+                    'position' => 'position_1',
+                    'disabled' => 'true'
+                ],
+                [
+                    'label' => 'label_2',
+                    'position' => 'position_2',
+                    'disabled' => 'true'
+                ]
+            ],
+            [
+                [
+                    'label' => null,
+                    'position' => null,
+                    'disabled' => null
+                ],
+                [
+                    'label' => null,
+                    'position' => null,
+                    'disabled' => null
+                ]
+            ]
+        ];
+    }
+
+    /**
+     * @dataProvider validateDataProvider
+     * @param bool $value
+     */
+    public function testValidate($value)
+    {
+        $attributeCode = 'attr_code';
+        $attribute = $this->getMock(
+            'Magento\Eav\Model\Entity\Attribute',
+            ['getAttributeCode', 'getIsRequired', 'isValueEmpty', 'getIsUnique', 'getEntityType', '__wakeup'],
+            [],
+            '',
+            false
+        );
+        $attributeEntity = $this->getMock(
+            '\Magento\Framework\Model\Resource\AbstractResourceAbstractEntity',
+            ['checkAttributeUniqueValue']
+        );
+        $attribute->expects($this->any())->method('getAttributeCode')->will($this->returnValue($attributeCode));
+        $attribute->expects($this->any())->method('getIsRequired')->will($this->returnValue(true));
+        $attribute->expects($this->any())->method('isValueEmpty')->will($this->returnValue($value));
+        $attribute->expects($this->any())->method('getIsUnique')->will($this->returnValue(true));
+        $attribute->expects($this->any())->method('getEntityType')->will($this->returnValue($attributeEntity));
+        $attributeEntity->expects($this->any())->method('checkAttributeUniqueValue')->will($this->returnValue(true));
+
+        $this->model->setAttribute($attribute);
+        $this->dataObject->setData(['attr_code' => 'attribute data']);
+        $this->assertEquals(!$value, $this->model->validate($this->dataObject));
+    }
+
+    public function validateDataProvider()
+    {
+        return [
+            [true],
+            [false]
+        ];
+    }
+
+    /**
+     * @dataProvider beforeSaveDataProvider
+     * @param array $value
+     */
+    public function testBeforeSave($value)
+    {
+        $attributeCode = 'attr_code';
+        $attribute = $this->getMock(
+            'Magento\Eav\Model\Entity\Attribute',
+            ['getAttributeCode', 'getIsRequired', 'isValueEmpty', 'getIsUnique', 'getEntityType', '__wakeup'],
+            [],
+            '',
+            false
+        );
+        $mediaAttributes = [
+            'image' => $attribute,
+            'small_image' => $attribute,
+            'thumbnail' => $attribute
+        ];
+        $attribute->expects($this->any())->method('getAttributeCode')->will($this->returnValue($attributeCode));
+        $this->dataObject->expects($this->any())->method('getIsDuplicate')->will($this->returnValue(false));
+        $this->model->setAttribute($attribute);
+        $this->dataObject->setData(['attr_code' => ['images' => $value]]);
+        $this->dataObject->expects($this->any())->method('getMediaAttributes')
+            ->will(($this->returnValue($mediaAttributes)));
+        $this->model->beforeSave($this->dataObject);
+        foreach ($this->dataObject['attr_code']['images'] as $imageType => $imageData) {
+            if (isset($imageData['new_file'])) {
+                $value[$imageType]['file'] = $imageData['file'];
+                $value[$imageType]['new_file'] = $imageData['new_file'];
+            }
+            $this->assertEquals($value[$imageType], $imageData);
+        }
+    }
+
+    public function beforeSaveDataProvider()
+    {
+        return [
+            [
+                [
+                    'image_1' => [
+                        'position' => '1',
+                        'file' => '/m/y/mydrawing1.jpg.tmp',
+                        'value_id' => '',
+                        'label' => 'image 1',
+                        'disableed' => '0',
+                        'removed' => ''
+                    ],
+                    'image_2' => [
+                        'position' => '1',
+                        'file' => '/m/y/mydrawing2.jpg.tmp',
+                        'value_id' => '',
+                        'label' => 'image 2',
+                        'disableed' => '0',
+                        'removed' => ''
+                    ],
+                    'image_removed' => [
+                        'position' => '1',
+                        'file' => '/m/y/mydrawing3.jpg.tmp',
+                        'value_id' => '',
+                        'label' => 'image 3',
+                        'disableed' => '0',
+                        'removed' => '1'
+                    ]
+                ]
+            ]
+        ];
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/InputtypeTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/InputtypeTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..96c24b9627a52c071fd3bd4072226d86b5527448
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/InputtypeTest.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Model\Product\Attribute\Source;
+
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+
+class InputtypeTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Catalog\Model\Product\Attribute\Source\Inputtype */
+    protected $inputtypeModel;
+
+    /** @var ObjectManagerHelper */
+    protected $objectManagerHelper;
+
+    /** @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject */
+    protected $registry;
+
+    protected function setUp()
+    {
+        $this->registry = $this->getMock('Magento\Framework\Registry');
+
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->inputtypeModel = $this->objectManagerHelper->getObject(
+            'Magento\Catalog\Model\Product\Attribute\Source\Inputtype',
+            [
+                'coreRegistry' => $this->registry
+            ]
+        );
+    }
+
+    public function testToOptionArray()
+    {
+        $inputTypesSet = array(
+            array('value' => 'text', 'label' => 'Text Field'),
+            array('value' => 'textarea', 'label' => 'Text Area'),
+            array('value' => 'date', 'label' => 'Date'),
+            array('value' => 'boolean', 'label' => 'Yes/No'),
+            array('value' => 'multiselect', 'label' => 'Multiple Select'),
+            array('value' => 'select', 'label' => 'Dropdown'),
+            array('value' => 'price', 'label' => 'Price'),
+            array('value' => 'media_image', 'label' => 'Media Image')
+        );
+
+        $this->registry->expects($this->once())->method('registry');
+        $this->registry->expects($this->once())->method('register');
+        $this->assertEquals($inputTypesSet, $this->inputtypeModel->toOptionArray());
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/LayoutTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/LayoutTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a8dc938f62d429a75082bf1ab8b20679ad489359
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/LayoutTest.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Model\Product\Attribute\Source;
+
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+
+class LayoutTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Catalog\Model\Product\Attribute\Source\Layout */
+    protected $layoutModel;
+
+    /** @var ObjectManagerHelper */
+    protected $objectManagerHelper;
+
+    /** @var \Magento\Theme\Model\Layout\Source\Layout|\PHPUnit_Framework_MockObject_MockObject */
+    protected $layoutSourceModel;
+
+    protected function setUp()
+    {
+        $this->layoutSourceModel = $this->getMock(
+            'Magento\Theme\Model\Layout\Source\Layout',
+            array(
+                'toOptionArray'
+            ),
+            array(),
+            '',
+            false
+        );
+
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->layoutModel = $this->objectManagerHelper->getObject(
+            'Magento\Catalog\Model\Product\Attribute\Source\Layout',
+            array(
+                'pageSourceLayout' => $this->layoutSourceModel
+            )
+        );
+    }
+
+    public function testGetAllOptions()
+    {
+        $expectedOptions = array(
+            '0' => array('value' => '', 'label' => 'No layout updates'),
+            '1' => array('value' => 'option_value', 'label' => 'option_label')
+        );
+        $this->layoutSourceModel->expects($this->once())->method('toOptionArray')
+            ->will($this->returnValue(array('0' => $expectedOptions['1'])));
+        $layoutOptions = $this->layoutModel->getAllOptions();
+        $this->assertEquals($expectedOptions, $layoutOptions);
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/EnabledTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/EnabledTest.php
index 1f06fb62afb7a2564e28c9e3b81f219719959044..e0cf332202c6ee537b1c95819b3de74918aadbea 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/EnabledTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/EnabledTest.php
@@ -38,7 +38,7 @@ class EnabledTest extends \PHPUnit_Framework_TestCase
         $this->_model = $objectManager->getObject('Magento\Catalog\Model\Product\Attribute\Source\Msrp\Type\Enabled');
     }
 
-    public function testGetFlatColums()
+    public function testGetFlatColumns()
     {
         $abstractAttributeMock = $this->getMock(
             '\Magento\Eav\Model\Entity\Attribute\AbstractAttribute',
@@ -52,18 +52,18 @@ class EnabledTest extends \PHPUnit_Framework_TestCase
 
         $this->_model->setAttribute($abstractAttributeMock);
 
-        $flatColums = $this->_model->getFlatColums();
+        $flatColumns = $this->_model->getFlatColumns();
 
-        $this->assertTrue(is_array($flatColums), 'FlatColums must be an array value');
-        $this->assertTrue(!empty($flatColums), 'FlatColums must be not empty');
-        foreach ($flatColums as $result) {
-            $this->assertArrayHasKey('unsigned', $result, 'FlatColums must have "unsigned" column');
-            $this->assertArrayHasKey('default', $result, 'FlatColums must have "default" column');
-            $this->assertArrayHasKey('extra', $result, 'FlatColums must have "extra" column');
-            $this->assertArrayHasKey('type', $result, 'FlatColums must have "type" column');
-            $this->assertArrayHasKey('nullable', $result, 'FlatColums must have "nullable" column');
-            $this->assertArrayHasKey('comment', $result, 'FlatColums must have "comment" column');
-            $this->assertArrayHasKey('length', $result, 'FlatColums must have "length" column');
+        $this->assertTrue(is_array($flatColumns), 'FlatColumns must be an array value');
+        $this->assertTrue(!empty($flatColumns), 'FlatColumns must be not empty');
+        foreach ($flatColumns as $result) {
+            $this->assertArrayHasKey('unsigned', $result, 'FlatColumns must have "unsigned" column');
+            $this->assertArrayHasKey('default', $result, 'FlatColumns must have "default" column');
+            $this->assertArrayHasKey('extra', $result, 'FlatColumns must have "extra" column');
+            $this->assertArrayHasKey('type', $result, 'FlatColumns must have "type" column');
+            $this->assertArrayHasKey('nullable', $result, 'FlatColumns must have "nullable" column');
+            $this->assertArrayHasKey('comment', $result, 'FlatColumns must have "comment" column');
+            $this->assertArrayHasKey('length', $result, 'FlatColumns must have "length" column');
         }
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/PriceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/PriceTest.php
index 0295201caa55d10b2e507e3958fcbb1815fed0b9..cbef25f0bc895ccd8d58b3b1479249c57316e79d 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/PriceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/Msrp/Type/PriceTest.php
@@ -38,7 +38,7 @@ class PriceTest extends \PHPUnit_Framework_TestCase
         $this->_model = $objectManager->getObject('Magento\Catalog\Model\Product\Attribute\Source\Msrp\Type\Price');
     }
 
-    public function testGetFlatColums()
+    public function testGetFlatColumns()
     {
         $abstractAttributeMock = $this->getMock(
             '\Magento\Eav\Model\Entity\Attribute\AbstractAttribute',
@@ -52,16 +52,16 @@ class PriceTest extends \PHPUnit_Framework_TestCase
 
         $this->_model->setAttribute($abstractAttributeMock);
 
-        $flatColums = $this->_model->getFlatColums();
+        $flatColumns = $this->_model->getFlatColumns();
 
-        $this->assertTrue(is_array($flatColums), 'FlatColums must be an array value');
-        $this->assertTrue(!empty($flatColums), 'FlatColums must be not empty');
-        foreach ($flatColums as $result) {
-            $this->assertArrayHasKey('unsigned', $result, 'FlatColums must have "unsigned" column');
-            $this->assertArrayHasKey('default', $result, 'FlatColums must have "default" column');
-            $this->assertArrayHasKey('extra', $result, 'FlatColums must have "extra" column');
-            $this->assertArrayHasKey('type', $result, 'FlatColums must have "type" column');
-            $this->assertArrayHasKey('nullable', $result, 'FlatColums must have "nullable" column');
+        $this->assertTrue(is_array($flatColumns), 'FlatColumns must be an array value');
+        $this->assertTrue(!empty($flatColumns), 'FlatColumns must be not empty');
+        foreach ($flatColumns as $result) {
+            $this->assertArrayHasKey('unsigned', $result, 'FlatColumns must have "unsigned" column');
+            $this->assertArrayHasKey('default', $result, 'FlatColumns must have "default" column');
+            $this->assertArrayHasKey('extra', $result, 'FlatColumns must have "extra" column');
+            $this->assertArrayHasKey('type', $result, 'FlatColumns must have "type" column');
+            $this->assertArrayHasKey('nullable', $result, 'FlatColumns must have "nullable" column');
         }
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/StatusTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/StatusTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..62df524b9b0fa61c3a71837d2bbb389b901d45fc
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Source/StatusTest.php
@@ -0,0 +1,171 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Model\Product\Attribute\Source;
+
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+
+class StatusTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Catalog\Model\Product\Attribute\Source\Status */
+    protected $status;
+
+    /** @var ObjectManagerHelper */
+    protected $objectManagerHelper;
+
+    /** @var \Magento\Eav\Model\Entity\Collection\AbstractCollection|\PHPUnit_Framework_MockObject_MockObject */
+    protected $collection;
+
+    /** @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeModel;
+
+    /** @var \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend|\PHPUnit_Framework_MockObject_MockObject */
+    protected $backendAttributeModel;
+
+    protected function setUp()
+    {
+
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->collection = $this->getMock(
+            '\Magento\Catalog\Model\Resource\Product\Collection',
+            array(
+                '__wakeup',
+                'getSelect',
+                'joinLeft',
+                'order',
+                'getStoreId',
+                'getConnection',
+                'getCheckSql'
+            ),
+            array(),
+            '',
+            false
+        );
+        $this->attributeModel = $this->getMock(
+            '\Magento\Catalog\Model\Entity\Attributee',
+            array(
+                '__wakeup',
+                'getAttributeCode',
+                'getBackend',
+                'getId',
+                'isScopeGlobal',
+            ),
+            array(),
+            '',
+            false
+        );
+        $this->backendAttributeModel = $this->getMock(
+            '\Magento\Catalog\Model\Product\Attribute\Backend\Sku', array('__wakeup', 'getTable'), array(), '', false);
+        $this->status = $this->objectManagerHelper->getObject(
+            'Magento\Catalog\Model\Product\Attribute\Source\Status'
+        );
+
+        $this->attributeModel->expects($this->any())->method('getAttribute')
+            ->will($this->returnSelf());
+        $this->attributeModel->expects($this->any())->method('getAttributeCode')
+            ->will($this->returnValue('attribute_code'));
+        $this->attributeModel->expects($this->any())->method('getId')
+            ->will($this->returnValue('1'));
+        $this->attributeModel->expects($this->any())->method('getBackend')
+            ->will($this->returnValue($this->backendAttributeModel));
+        $this->collection->expects($this->any())->method('getSelect')
+            ->will($this->returnSelf());
+        $this->collection->expects($this->any())->method('joinLeft')
+            ->will($this->returnSelf());
+        $this->backendAttributeModel->expects($this->any())->method('getTable')
+            ->will($this->returnValue('table_name'));
+    }
+
+    public function testAddValueSortToCollectionGlobal()
+    {
+
+        $this->attributeModel->expects($this->any())->method('isScopeGlobal')
+            ->will($this->returnValue(true));
+        $this->collection->expects($this->once())->method('order')->with('attribute_code_t.value asc')
+            ->will($this->returnSelf());
+
+        $this->status->setAttribute($this->attributeModel);
+        $this->status->addValueSortToCollection($this->collection);
+    }
+
+    public function testAddValueSortToCollectionNotGlobal()
+    {
+        $this->attributeModel->expects($this->any())->method('isScopeGlobal')
+            ->will($this->returnValue(false));
+
+        $this->collection->expects($this->once())->method('order')->with('check_sql asc')
+            ->will($this->returnSelf());
+        $this->collection->expects($this->once())->method('getStoreId')
+            ->will($this->returnValue(1));
+        $this->collection->expects($this->any())->method('getConnection')
+            ->will($this->returnSelf());
+        $this->collection->expects($this->any())->method('getCheckSql')
+            ->will($this->returnValue('check_sql'));
+
+        $this->status->setAttribute($this->attributeModel);
+        $this->status->addValueSortToCollection($this->collection);
+    }
+
+    public function testGetVisibleStatusIds()
+    {
+        $this->assertEquals(array(0 => 1), $this->status->getVisibleStatusIds());
+    }
+
+    public function testGetSaleableStatusIds()
+    {
+        $this->assertEquals(array(0 => 1), $this->status->getSaleableStatusIds());
+    }
+
+    public function testGetOptionArray()
+    {
+        $this->assertEquals(array(1 => 'Enabled', 2 => 'Disabled'), $this->status->getOptionArray());
+    }
+
+    /**
+     * @dataProvider getOptionTextDataProvider
+     * @param string $text
+     * @param string $id
+     */
+    public function testGetOptionText($text, $id)
+    {
+        $this->assertEquals($text, $this->status->getOptionText($id));
+    }
+
+    /**
+     * @return array
+     */
+    public function getOptionTextDataProvider()
+    {
+        return array(
+            array(
+                'text' => 'Enabled',
+                'id' => '1'
+            ),
+            array(
+                'text' => 'Disabled',
+                'id' => '2'
+            )
+        );
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/VisibilityTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/VisibilityTest.php
index 0f1b303fe60103bbca16a835c33b6515113e58d3..07d1a7855ec36d80d6b01e0210e6549f58d6dbfc 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/VisibilityTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/VisibilityTest.php
@@ -38,7 +38,7 @@ class VisibilityTest extends \PHPUnit_Framework_TestCase
         $this->_model = $objectManager->getObject('Magento\Catalog\Model\Product\Visibility');
     }
 
-    public function testGetFlatColums()
+    public function testGetFlatColumns()
     {
         $abstractAttributeMock = $this->getMock(
             '\Magento\Eav\Model\Entity\Attribute\AbstractAttribute',
@@ -52,17 +52,17 @@ class VisibilityTest extends \PHPUnit_Framework_TestCase
 
         $this->_model->setAttribute($abstractAttributeMock);
 
-        $flatColums = $this->_model->getFlatColums();
+        $flatColumns = $this->_model->getFlatColumns();
 
-        $this->assertTrue(is_array($flatColums), 'FlatColums must be an array value');
-        $this->assertTrue(!empty($flatColums), 'FlatColums must be not empty');
-        foreach ($flatColums as $result) {
-            $this->assertArrayHasKey('unsigned', $result, 'FlatColums must have "unsigned" column');
-            $this->assertArrayHasKey('default', $result, 'FlatColums must have "default" column');
-            $this->assertArrayHasKey('extra', $result, 'FlatColums must have "extra" column');
-            $this->assertArrayHasKey('type', $result, 'FlatColums must have "type" column');
-            $this->assertArrayHasKey('nullable', $result, 'FlatColums must have "nullable" column');
-            $this->assertArrayHasKey('comment', $result, 'FlatColums must have "comment" column');
+        $this->assertTrue(is_array($flatColumns), 'FlatColumns must be an array value');
+        $this->assertTrue(!empty($flatColumns), 'FlatColumns must be not empty');
+        foreach ($flatColumns as $result) {
+            $this->assertArrayHasKey('unsigned', $result, 'FlatColumns must have "unsigned" column');
+            $this->assertArrayHasKey('default', $result, 'FlatColumns must have "default" column');
+            $this->assertArrayHasKey('extra', $result, 'FlatColumns must have "extra" column');
+            $this->assertArrayHasKey('type', $result, 'FlatColumns must have "type" column');
+            $this->assertArrayHasKey('nullable', $result, 'FlatColumns must have "nullable" column');
+            $this->assertArrayHasKey('comment', $result, 'FlatColumns must have "comment" column');
         }
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php
index b73e577eff08f56a71d7faaa13e2887803c3b5d1..bb769ece2d1e0e1e8b7e666d4e84e19ec448f656 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php
@@ -39,7 +39,11 @@ class ProductRepositoryTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $productFactoryMock = $this->getMock(
-            'Magento\Catalog\Model\ProductFactory', array('create'), array(), '', false
+            'Magento\Catalog\Model\ProductFactory',
+            array('create'),
+            array(),
+            '',
+            false
         );
         $this->productMock = $this->getMock('Magento\Catalog\Model\Product', array(), array(), '', false);
         $productFactoryMock->expects($this->once())->method('create')->will($this->returnValue($this->productMock));
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Data/ConverterTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Data/ConverterTest.php
index bd29d60303e98d5cd65dc85b2349eac11b0fd8bd..2a403a9e9c5ecea984145e17cee4b4f120e29b89 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Data/ConverterTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Data/ConverterTest.php
@@ -54,15 +54,29 @@ class ConverterTest extends \PHPUnit_Framework_TestCase
         $productModelMock = $this->getMockBuilder('\Magento\Catalog\Model\Product')
             ->disableOriginalConstructor()
             ->getMock();
-        $attrCodes = ['sku', 'price', 'status', 'updatedAt', 'entity_id'];
-        $this->productBuilder->expects($this->once())
-            ->method('getCustomAttributesCodes')
-            ->will($this->returnValue($attrCodes));
+
+        $attrMock = $this->getMockBuilder('\Magento\Catalog\Model\Resource\Eav\Attribute')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $attrMock->expects($this->at(0))->method('getAttributeCode')->will($this->returnValue('sku'));
+        $attrMock->expects($this->at(1))->method('getAttributeCode')->will($this->returnValue('price'));
+        $attrMock->expects($this->at(2))->method('getAttributeCode')->will($this->returnValue('status'));
+        $attrMock->expects($this->at(3))->method('getAttributeCode')->will($this->returnValue('updatedAt'));
+        $attrMock->expects($this->at(4))->method('getAttributeCode')->will($this->returnValue('entity_id'));
+        $attrMock->expects($this->at(5))->method('getAttributeCode')->will($this->returnValue('store_id'));
+
+        $attrList = [$attrMock, $attrMock, $attrMock, $attrMock, $attrMock, $attrMock];
+
+        $productModelMock->expects($this->once())
+            ->method('getAttributes')
+            ->will($this->returnValue($attrList));
 
         $attributes = [
             ProductDataObject::SKU => ProductDataObject::SKU . 'value',
             ProductDataObject::PRICE => ProductDataObject::PRICE . 'value',
-            ProductDataObject::STATUS => ProductDataObject::STATUS . 'dataValue'
+            ProductDataObject::STATUS => ProductDataObject::STATUS . 'dataValue',
+            ProductDataObject::STORE_ID => ProductDataObject::STORE_ID . 'value'
         ];
         $this->productBuilder->expects($this->once())
             ->method('populateWithArray')
@@ -84,10 +98,14 @@ class ConverterTest extends \PHPUnit_Framework_TestCase
                 return null;
             }
         );
-        $productModelMock->expects($this->exactly(count($attrCodes)))
+        $productModelMock->expects($this->exactly(count($attrList)))
             ->method('getDataUsingMethod')
             ->will($dataUsingMethodCallback);
 
+        $productModelMock->expects($this->once())
+            ->method('getStoreId')
+            ->will($this->returnValue(ProductDataObject::STORE_ID . 'value'));
+
         $dataCallback = $this->returnCallback(
             function ($attrCode) {
                 if ($attrCode == 'status') {
@@ -96,7 +114,7 @@ class ConverterTest extends \PHPUnit_Framework_TestCase
                 return null;
             }
         );
-        $productModelMock->expects($this->exactly(2))
+        $productModelMock->expects($this->exactly(3))
             ->method('getData')
             ->will($dataCallback);
 
@@ -105,6 +123,7 @@ class ConverterTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals(ProductDataObject::SKU . 'value', $productData->getSku());
         $this->assertEquals(ProductDataObject::PRICE . 'value', $productData->getPrice());
         $this->assertEquals(ProductDataObject::STATUS . 'dataValue', $productData->getStatus());
+        $this->assertEquals(ProductDataObject::STORE_ID . 'value', $productData->getStoreId());
         $this->assertEquals(null, $productData->getUpdatedAt());
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/CheckoutAgreements/Model/AgreementTest.php b/dev/tests/unit/testsuite/Magento/CheckoutAgreements/Model/AgreementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4dbdafbd74763a598d2feb8acc8b0dddd2098110
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/CheckoutAgreements/Model/AgreementTest.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CheckoutAgreements\Model;
+
+class AgreementTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\CheckoutAgreements\Model\Agreement
+     */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->model = $this->objectManager->getObject('\Magento\CheckoutAgreements\Model\Agreement');
+    }
+
+    /**
+     * @covers \Magento\CheckoutAgreements\Model\Agreement::validateData
+     *
+     * @dataProvider validateDataDataProvider
+     * @param \Magento\Framework\Object $inputData
+     * @param array|bool $expectedResult
+     */
+    public function testValidateData($inputData, $expectedResult)
+    {
+        $this->assertEquals($expectedResult, $this->model->validateData($inputData));
+    }
+
+    /**
+     * @return array
+     */
+    public function validateDataDataProvider()
+    {
+        return [
+            [
+                'inputData' => (new \Magento\Framework\Object())->setContentHeight('1px'),
+                'expectedResult' => true
+            ],
+            [
+                'inputData' => (new \Magento\Framework\Object())->setContentHeight('1.1px'),
+                'expectedResult' => true
+            ],
+            [
+                'inputData' => (new \Magento\Framework\Object())->setContentHeight('0.1in'),
+                'expectedResult' => true
+            ],
+            [
+                'inputData' => (new \Magento\Framework\Object())->setContentHeight('5%'),
+                'expectedResult' => true
+            ],
+            [
+                'inputData' => (new \Magento\Framework\Object())->setContentHeight('5'),
+                'expectedResult' => true
+            ],
+            [
+                'inputData' => (new \Magento\Framework\Object())->setContentHeight('px'),
+                'expectedResult' => [
+                    "Please input a valid CSS-height. For example 100px or 77pt or 20em or .5ex or 50%."
+                ]
+            ],
+            [
+                'inputData' => (new \Magento\Framework\Object())->setContentHeight('abracadabra'),
+                'expectedResult' => [
+                    "Please input a valid CSS-height. For example 100px or 77pt or 20em or .5ex or 50%."
+                ]
+            ],
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Cms/Model/Resource/Block/Grid/CollectionTest.php b/dev/tests/unit/testsuite/Magento/Cms/Model/Resource/Block/Grid/CollectionTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4f757d8e1f5bb377fb30385197a298cf538a2bd4
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Cms/Model/Resource/Block/Grid/CollectionTest.php
@@ -0,0 +1,105 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Cms\Model\Resource\Block\Grid;
+
+class CollectionTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Collection|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $collection;
+
+    /**
+     * @var \Magento\Framework\DB\Select|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $select;
+
+    protected function setUp()
+    {
+        $this->select = $this->getMockBuilder('Magento\Framework\DB\Select')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $connection = $this->getMockBuilder('Magento\Framework\DB\Adapter\Pdo\Mysql')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $connection->expects($this->any())
+            ->method('select')
+            ->will($this->returnValue($this->select));
+
+        $resource = $this->getMockBuilder('Magento\Framework\Model\Resource\Db\AbstractDb')
+            ->disableOriginalConstructor()
+            ->setMethods(['__wakeup', 'getReadConnection'])
+            ->getMockForAbstractClass();
+        $resource->expects($this->any())
+            ->method('getReadConnection')
+            ->will($this->returnValue($connection));
+
+        $objectManagerHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $arguments = $objectManagerHelper->getConstructArguments(
+            'Magento\Cms\Model\Resource\Block\Grid\Collection',
+            ['resource' => $resource, 'connection' => $connection]
+        );
+
+        $this->collection = $this->getMockBuilder('Magento\Cms\Model\Resource\Block\Grid\Collection')
+            ->setConstructorArgs($arguments)
+            ->setMethods(['addFilter', '_translateCondition', 'getMainTable'])
+            ->getMock();
+    }
+
+    public function testAddFieldToFilterSore()
+    {
+        $storeId = 1;
+        $this->collection->expects($this->once())
+            ->method('addFilter')
+            ->with(
+                $this->equalTo('store'),
+                $this->equalTo(array('in' => [$storeId])),
+                $this->equalTo('public')
+            );
+        $this->collection->addFieldToFilter('store_id', $storeId);
+    }
+
+    public function testAddFieldToFilter()
+    {
+        $field = 'title';
+        $value = 'test_filter';
+        $searchSql = 'sql query';
+
+        $this->collection->expects($this->once())
+            ->method('_translateCondition')
+            ->with($field, $value)
+            ->will($this->returnValue($searchSql));
+
+        $this->select->expects($this->once())
+            ->method('where')
+            ->with(
+                $this->equalTo($searchSql),
+                $this->equalTo(null),
+                $this->equalTo(\Magento\Framework\DB\Select::TYPE_CONDITION)
+            );
+
+        $this->collection->addFieldToFilter($field, $value);
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php b/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php
index 7912f69c35eb94858d06ca2e1ef7e7f4e9be80f5..ffc5ba421f75a8bf17c068d6777b3ae8267acc9e 100644
--- a/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php
+++ b/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php
@@ -31,7 +31,7 @@ namespace Magento\ConfigurableProduct\Model\Product\Type;
 class ConfigurableTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable
+     * @var Configurable
      */
     protected $_model;
 
@@ -50,6 +50,11 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase
      */
     protected $_attributeCollectionFactory;
 
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $_productCollectionFactory;
+
     /**
      * @var \Magento\TestFramework\Helper\ObjectManager
      */
@@ -90,9 +95,9 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $productColFactory = $this->getMock(
+        $this->_productCollectionFactory = $this->getMock(
             'Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Product\CollectionFactory',
-            array(),
+            array('create'),
             array(),
             '',
             false
@@ -113,7 +118,7 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase
                 'attributeSetFactory' => $setFactoryMock,
                 'eavAttributeFactory' => $attributeFactoryMock,
                 'configurableAttributeFactory' => $this->_configurableAttributeFactoryMock,
-                'productCollectionFactory' => $productColFactory,
+                'productCollectionFactory' => $this->_productCollectionFactory,
                 'attributeCollectionFactory' => $this->_attributeCollectionFactory,
                 'eventManager' => $eventManager,
                 'coreData' => $coreDataMock,
@@ -233,4 +238,56 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase
 
         $this->assertTrue($this->_model->canUseAttribute($attribute));
     }
-}
+
+    public function testgetUsedProducts()
+    {
+        $attributeCollection = $this->getMockBuilder(
+            '\Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Attribute\Collection'
+        )->setMethods(['setProductFilter', 'addFieldToFilter', 'walk'])->disableOriginalConstructor()
+            ->getMock();
+        $attributeCollection->expects($this->any())->method('setProductFilter')->will($this->returnSelf());
+        $this->_attributeCollectionFactory->expects($this->any())->method('create')
+            ->will($this->returnValue($attributeCollection));
+        $product = $this->getMockBuilder('\Magento\Catalog\Model\Product')
+            ->setMethods(['dataHasChangedFor', 'getConfigurableAttributesData', 'getStoreId',
+                          'getId', 'getData', 'hasData', 'getAssociatedProductIds', '__wakeup', '__sleep'
+            ])->disableOriginalConstructor()
+            ->getMock();
+        $attributeData = [1 => [
+            'id' => 1,
+            'code' => 'someattr',
+            'attribute_id' => 111,
+            'position' => 0,
+            'label' => 'Some Super Attribute',
+            'values' => []
+        ]];
+        $product->expects($this->any())->method('getConfigurableAttributesData')
+            ->will($this->returnValue($attributeData));
+        $product->expects($this->any())->method('getStoreId')->will($this->returnValue(5));
+        $product->expects($this->any())->method('getId')->will($this->returnValue(1));
+        $product->expects($this->any())->method('getAssociatedProductIds')->will($this->returnValue([2]));
+        $product->expects($this->any())->method('hasData')
+            ->will($this->returnValueMap([
+                ['_cache_instance_used_product_attribute_ids', 1],
+                ['_cache_instance_products', 0],
+                ['_cache_instance_configurable_attributes', 1],
+            ]));
+        $product->expects($this->any())->method('getData')
+            ->will($this->returnValue(1));
+        $productCollection = $this->getMockBuilder(
+            'Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Product\Collection'
+        )->setMethods(
+            ['setFlag', 'setProductFilter', 'addStoreFilter', 'addAttributeToSelect', 'addFilterByRequiredOptions',
+             'setStoreId']
+        )->disableOriginalConstructor()
+            ->getMock();
+        $productCollection->expects($this->any())->method('addAttributeToSelect')->will($this->returnSelf());
+        $productCollection->expects($this->any())->method('setProductFilter')->will($this->returnSelf());
+        $productCollection->expects($this->any())->method('setFlag')->will($this->returnSelf());
+        $productCollection->expects($this->any())->method('addFilterByRequiredOptions')->will($this->returnSelf());
+        $productCollection->expects($this->any())->method('setStoreId')->with(5)->will($this->returnValue([]));
+        $this->_productCollectionFactory->expects($this->any())->method('create')
+            ->will($this->returnValue($productCollection));
+        $this->_model->getUsedProducts($product);
+    }
+}
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Service/V1/Product/Link/ReadServiceTest.php b/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Service/V1/Product/Link/ReadServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..075de0e2d3b6a1d87873a491fdc20812c26f769f
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Service/V1/Product/Link/ReadServiceTest.php
@@ -0,0 +1,120 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\ConfigurableProduct\Service\V1\Product\Link;
+
+class ReadServiceTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Catalog\Model\ProductRepository|\PHPUnit_Framework_MockObject_MockObject */
+    protected $productRepository;
+    /** @var \Magento\Catalog\Service\V1\Data\Converter|\PHPUnit_Framework_MockObject_MockObject */
+    protected $productConverter;
+    /** @var \Magento\TestFramework\Helper\ObjectManager */
+    protected $objectManagerHelper;
+    /** @var \Magento\ConfigurableProduct\Service\V1\Product\Link\ReadService */
+    protected $object;
+
+    public function setUp()
+    {
+        $this->productRepository = $this->getMockBuilder('Magento\\Catalog\\Model\\ProductRepository')
+            ->disableOriginalConstructor()->getMock();
+        $this->productConverter = $this->getMockBuilder('Magento\\Catalog\\Service\\V1\\Data\\Converter')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->objectManagerHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->object = $this->objectManagerHelper->getObject(
+            'Magento\\ConfigurableProduct\\Service\\V1\\Product\\Link\\ReadService',
+            ['productRepository' => $this->productRepository, 'productConverter' => $this->productConverter]
+        );
+    }
+
+    public function testGetChildren()
+    {
+        $productId = 'sadasd';
+
+        $product = $this->getMockBuilder('Magento\Catalog\Model\Product')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $productTypeInstance = $this->getMockBuilder('Magento\ConfigurableProduct\Model\Product\Type\Configurable')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $product->expects($this->any())->method('getTypeId')->will(
+            $this->returnValue(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE)
+        );
+
+        $product->expects($this->any())->method('getTypeInstance')->will(
+            $this->returnValue($productTypeInstance)
+        );
+
+        $productTypeInstance->expects($this->once())->method('setStoreFilter')
+            ->with(null, $product);
+
+        $childProduct = $this->getMockBuilder('Magento\Catalog\Model\Product')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $productTypeInstance->expects($this->any())->method('getUsedProducts')
+            ->with($product)->will($this->returnValue([$childProduct]));
+
+        $this->productRepository->expects($this->any())
+            ->method('get')->with($productId)
+            ->will(
+                $this->returnValue($product)
+            );
+
+        $productDto = $this->getMockBuilder('Magento\Catalog\Service\V1\Data\Product')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->productConverter->expects($this->any())
+            ->method('createProductDataFromModel')->with($childProduct)
+            ->will(
+                $this->returnValue($productDto)
+            );
+
+        $products = $this->object->getChildren($productId);
+        $this->assertCount(1, $products);
+        $this->assertEquals($productDto, $products[0]);
+    }
+
+    public function testGetChildrenException()
+    {
+        $product = $this->getMockBuilder('Magento\Catalog\Model\Product')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $product->expects($this->any())->method('getTypeId')->will(
+            $this->returnValue('same')
+        );
+
+        $this->productRepository->expects($this->any())
+            ->method('get')->with('sd')
+            ->will(
+                $this->returnValue($product)
+            );
+        $this->assertCount(0, $this->object->getChildren('sd'));
+    }
+}
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Service/V1/Product/Link/WriteServiceTest.php b/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Service/V1/Product/Link/WriteServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e2c582fbba3ed5b077fb5583bc1b0a9b16b973cd
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Service/V1/Product/Link/WriteServiceTest.php
@@ -0,0 +1,189 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\ConfigurableProduct\Service\V1\Product\Link;
+
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class WriteServiceTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\ConfigurableProduct\Service\V1\Product\Link\WriteService
+     */
+    private $service;
+
+    /**
+     * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $product;
+
+    /**
+     * @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productType;
+
+    /** @var \Magento\Catalog\Model\ProductRepository|\PHPUnit_Framework_MockObject_MockObject */
+    protected $productRepository;
+
+    /** @var Configurable|\PHPUnit_Framework_MockObject_MockObject */
+    protected $configurableType;
+
+    protected function setUp()
+    {
+        $this->productType = $this->getMockBuilder('Magento\ConfigurableProduct\Model\Product\Type\Configurable')
+            ->setMethods(['getUsedProducts'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->product = $this->getMockBuilder('Magento\Catalog\Model\Product')
+            ->setMethods(['getTypeInstance', 'save', 'getTypeId', 'addData', '__wakeup'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->product
+            ->expects($this->any())
+            ->method('getTypeInstance')
+            ->will($this->returnValue($this->productType));
+
+        $this->productRepository = $this->getMockBuilder('Magento\Catalog\Model\ProductRepository')
+            ->setMethods(['get'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->configurableType =
+            $this->getMockBuilder('Magento\\ConfigurableProduct\\Model\\Resource\\Product\\Type\\Configurable')
+                ->disableOriginalConstructor()->getMock();
+
+        $this->service = (new ObjectManager($this))->getObject(
+            'Magento\ConfigurableProduct\Service\V1\Product\Link\WriteService',
+            [
+                'productRepository' => $this->productRepository,
+                'configurableType' => $this->configurableType
+            ]
+        );
+    }
+
+    public function testRemoveChild()
+    {
+        $productSku = 'configurable';
+        $childSku = 'simple_10';
+
+        $this->product
+            ->expects($this->any())
+            ->method('getTypeId')
+            ->will($this->returnValue(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE));
+        $this->productRepository->expects($this->any())->method('get')->will($this->returnValue($this->product));
+
+        $option = $this->getMockBuilder('\Magento\Catalog\Model\Product')
+            ->setMethods(['getSku', 'getId', '__wakeup'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $option->expects($this->any())->method('getSku')->will($this->returnValue($childSku));
+        $option->expects($this->any())->method('getId')->will($this->returnValue(10));
+        $this->productType->expects($this->once())->method('getUsedProducts')
+            ->will($this->returnValue([$option]));
+
+        $this->product->expects($this->once())->method('addData')->with(['associated_product_ids' => array()]);
+        $this->product->expects($this->once())->method('save');
+        $this->assertTrue($this->service->removeChild($productSku, $childSku));
+    }
+
+    /**
+     * @expectedException \Magento\Webapi\Exception
+     * @expectedExceptionCode 403
+     */
+    public function testRemoveChildForbidden()
+    {
+        $productSku = 'configurable';
+        $childSku = 'simple_10';
+
+        $this->product
+            ->expects($this->any())
+            ->method('getTypeId')
+            ->will($this->returnValue(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE));
+        $this->productRepository->expects($this->any())->method('get')->will($this->returnValue($this->product));
+        $this->service->removeChild($productSku, $childSku);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function testRemoveChildInvalidChildSku()
+    {
+        $productSku = 'configurable';
+        $childSku = 'simple_10';
+
+        $this->product
+            ->expects($this->any())
+            ->method('getTypeId')
+            ->will($this->returnValue(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE));
+        $this->productRepository->expects($this->any())->method('get')->will($this->returnValue($this->product));
+
+        $option = $this->getMockBuilder('\Magento\Catalog\Model\Product')
+            ->setMethods(['getSku', 'getId', '__wakeup'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $option->expects($this->any())->method('getSku')->will($this->returnValue($childSku . '_invalid'));
+        $option->expects($this->any())->method('getId')->will($this->returnValue(10));
+        $this->productType->expects($this->once())->method('getUsedProducts')
+            ->will($this->returnValue([$option]));
+
+        $this->service->removeChild($productSku, $childSku);
+    }
+
+    public function testAddChild()
+    {
+        $productSku = 'configurable-sku';
+        $childSku = 'simple-sku';
+
+        $configurable = $this->getMockBuilder('Magento\Catalog\Model\Product')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $configurable->expects($this->any())->method('getId')->will($this->returnValue(666));
+
+        $simplee = $this->getMockBuilder('Magento\Catalog\Model\Product')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $simplee->expects($this->any())->method('getId')->will($this->returnValue(999));
+
+        $this->productRepository->expects($this->at(0))->method('get')->with($productSku)->will(
+            $this->returnValue($configurable)
+        );
+
+        $this->productRepository->expects($this->at(1))->method('get')->with($childSku)->will(
+            $this->returnValue($simplee)
+        );
+
+        $this->configurableType->expects($this->once())->method('getChildrenIds')->with(666)
+            ->will(
+                $this->returnValue([0 => [1, 2, 3]])
+            );
+        $configurable->expects($this->once())->method('__call')->with('setAssociatedProductIds', [[1, 2, 3, 999]]);
+        $configurable->expects($this->once())->method('save');
+
+        $this->assertTrue(true, $this->service->addChild($productSku, $childSku));
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Service/V1/ReadServiceTest.php b/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Service/V1/ReadServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6e3c86f66799ea77e5bfcc32a39e4705e0459958
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Service/V1/ReadServiceTest.php
@@ -0,0 +1,188 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\ConfigurableProduct\Service\V1;
+
+use Magento\Catalog\Service\V1\Data\Product;
+use Magento\Catalog\Service\V1\Data\ProductBuilder;
+use Magento\Catalog\Service\V1\Product\Attribute\ReadServiceInterface;
+use Magento\ConfigurableProduct\Model\Product\Type\VariationMatrix;
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+
+class ReadServiceTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var ReadService */
+    protected $object;
+
+    /** @var ObjectManagerHelper */
+    protected $objectManagerHelper;
+
+    /** @var ReadServiceInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeReadService;
+
+    /**
+     * @var VariationMatrix|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $variationMatrix;
+
+    /**
+     * @var ProductBuilder|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productBuilder;
+
+    protected function setUp()
+    {
+        $this->attributeReadService = $this->getMockBuilder(
+            'Magento\Catalog\Service\V1\Product\Attribute\ReadServiceInterface'
+        )->disableOriginalConstructor()->getMock();
+
+        $this->variationMatrix = $this->getMockBuilder(
+            'Magento\ConfigurableProduct\Model\Product\Type\VariationMatrix'
+        )->disableOriginalConstructor()->getMock();
+
+        $this->productBuilder = $this->getMockBuilder(
+            'Magento\Catalog\Service\V1\Data\ProductBuilder'
+        )->disableOriginalConstructor()->getMock();
+
+
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->object = $this->objectManagerHelper->getObject(
+            'Magento\ConfigurableProduct\Service\V1\ReadService',
+            [
+                'attributeReadService' => $this->attributeReadService,
+                'variationMatrix' => $this->variationMatrix,
+                'productBuilder' => $this->productBuilder,
+            ]
+        );
+    }
+
+    /**
+     * @param array $configurableAttributeData
+     * @dataProvider productVariationDataProvider
+     */
+    public function testGenerateVariation($configurableAttributeData)
+    {
+        $attributeCode = 'code';
+        $attribute = $this->getMockBuilder('Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $attribute->expects($this->any())
+            ->method('getAttributeCode')
+            ->will($this->returnValue($attributeCode));
+
+
+        $this->attributeReadService->expects($this->once())
+            ->method('info')
+            ->with($configurableAttributeData['attribute_id'])
+            ->will($this->returnValue($attribute));
+
+        $options = null;
+        $this->variationMatrix->expects($this->any())
+            ->method('getVariations')
+            ->with(
+                [
+                    $configurableAttributeData['attribute_id'] => [
+                        "attribute_id" => $configurableAttributeData['attribute_id'],
+                        "values" => $configurableAttributeData['values'],
+                        "options" => $options,
+                        "attribute_code" => $attributeCode,
+                    ]
+                ]
+            )
+            ->will(
+                $this->returnValue(
+                    [
+                        [
+                            $configurableAttributeData['attribute_id'] => [
+                                'value' => '14',
+                                'label' => 'dd',
+                                'price' => [
+                                    'value_index' => 14,
+                                    'pricing_value' => 10,
+                                ],
+                            ],
+                        ],
+                    ]
+                )
+            );
+
+        $product = $this->getMockBuilder('Magento\Catalog\Service\V1\Data\Product')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $product->expects($this->any())
+            ->method('getPrice')
+            ->will($this->returnValue(100));
+
+        $configurableAttribute = $this->getMockBuilder(
+            'Magento\ConfigurableProduct\Service\V1\Data\ConfigurableAttribute'
+        )
+            ->disableOriginalConstructor()
+            ->getMock();
+        $configurableAttribute->expects($this->any())
+            ->method('__toArray')
+            ->will($this->returnValue($configurableAttributeData));
+        $configurableAttribute->expects($this->any())
+            ->method('getAttributeId')
+            ->will($this->returnValue($configurableAttributeData['attribute_id']));
+
+        $this->productBuilder->expects($this->any())
+            ->method('populute')
+            ->with($product);
+
+        $this->productBuilder->expects($this->once())
+            ->method('setCustomAttribute')
+            ->with($attributeCode, 14);
+        $this->productBuilder->expects($this->once())
+            ->method('setPrice')
+            ->with(110);
+
+        $this->productBuilder->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($product));
+
+        $result = $this->object->generateVariation($product, [$configurableAttribute]);
+        $this->assertCount(1, $result);
+        $this->assertEquals([$product], $result);
+
+    }
+
+    /**
+     * @return array
+     */
+    public function productVariationDataProvider()
+    {
+        return [
+            [
+                [
+                    "attribute_id" => 174,
+                    "values" => [
+                        [
+                            "index" => 14,
+                            "price" => 100.0
+                        ]
+                    ]
+                ]
+            ]
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Block/Adminhtml/From/Element/ImageTest.php b/dev/tests/unit/testsuite/Magento/Customer/Block/Adminhtml/From/Element/ImageTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..72bdfe972f4030c6144e71f018559d99ddcdc1c3
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Customer/Block/Adminhtml/From/Element/ImageTest.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Customer\Block\Adminhtml\From\Element;
+
+/**
+ * Test class for \Magento\Customer\Block\Adminhtml\From\Element\Image
+ */
+class ImageTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Customer\Block\Adminhtml\Form\Element\Image
+     */
+    protected $image;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $backendHelperMock;
+
+    protected function setUp()
+    {
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->backendHelperMock = $this->getMockBuilder('Magento\Backend\Helper\Data')
+            ->setMethods([])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->image = $objectManager->getObject(
+            'Magento\Customer\Block\Adminhtml\Form\Element\Image',
+            ['adminhtmlData' => $this->backendHelperMock]
+        );
+    }
+
+    public function testGetPreviewFile()
+    {
+        $value = 'image.jpg';
+        $url = 'http://example.com/backend/customer/index/viewfile/' . $value;
+        $formMock = $this->getMockBuilder('Magento\Framework\Data\Form')
+            ->disableOriginalConstructor()
+            ->setMethods([])
+            ->getMock();
+        $this->image->setForm($formMock);
+        $this->image->setValue($value);
+
+        $this->backendHelperMock->expects($this->once())
+            ->method('urlEncode')
+            ->with($value)
+            ->will($this->returnArgument(0));
+        $this->backendHelperMock->expects($this->once())
+            ->method('getUrl')
+            ->with('customer/index/viewfile', ['image' => $value])
+            ->will($this->returnValue($url));
+
+        $this->assertContains($url, $this->image->getElementHtml());
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/FirstEntranceTest.php b/dev/tests/unit/testsuite/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/FirstEntranceTest.php
index 2fb597f357a1ec4a9393ccc45df65eb38f48e4d3..a6840d0e39fb18a47752ce4856e44f164ed342ae 100644
--- a/dev/tests/unit/testsuite/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/FirstEntranceTest.php
+++ b/dev/tests/unit/testsuite/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/FirstEntranceTest.php
@@ -32,16 +32,16 @@ class FirstEntranceTest extends \PHPUnit_Framework_TestCase
     /**
      * @var \Magento\DesignEditor\Controller\Adminhtml\System\Design\Editor
      */
-    protected $_model;
+    protected $model;
 
     /**
      * @var \PHPUnit_Framework_MockObject_MockObject
      */
-    protected $_objectManagerMock;
+    protected $objectManagerMock;
 
     protected function setUp()
     {
-        $this->_objectManagerMock = $this->getMock('Magento\Framework\ObjectManager');
+        $this->objectManagerMock = $this->getMock('Magento\Framework\ObjectManager');
 
         $request = $this->getMock('Magento\Framework\App\Request\Http', array(), array(), '', false);
         $request->expects($this->any())->method('setActionName')->will($this->returnSelf());
@@ -70,10 +70,10 @@ class FirstEntranceTest extends \PHPUnit_Framework_TestCase
         $layoutMock->expects(
             $this->any()
         )->method(
-                'getNode'
-            )->will(
-                $this->returnValue(new \Magento\Framework\Simplexml\Element('<root />'))
-            );
+            'getNode'
+        )->will(
+            $this->returnValue(new \Magento\Framework\Simplexml\Element('<root />'))
+        );
         $blockMessage = $this->getMock(
             'Magento\Framework\View\Element\Messages',
             array('addMessages', 'setEscapeMessageFlag', 'addStorageType'),
@@ -100,7 +100,7 @@ class FirstEntranceTest extends \PHPUnit_Framework_TestCase
             'Magento\DesignEditor\Controller\Adminhtml\System\Design\Editor',
             array(
                 'request' => $request,
-                'objectManager' => $this->_objectManagerMock,
+                'objectManager' => $this->objectManagerMock,
                 'layout' => $layoutMock,
                 'invokeArgs' => array(
                     'helper' => $this->getMock('Magento\Backend\Helper\Data', array(), array(), '', false),
@@ -109,7 +109,7 @@ class FirstEntranceTest extends \PHPUnit_Framework_TestCase
             )
         );
 
-        $this->_model = $objectManagerHelper->getObject(
+        $this->model = $objectManagerHelper->getObject(
             'Magento\DesignEditor\Controller\Adminhtml\System\Design\Editor\FirstEntrance',
             $constructArguments
         );
@@ -121,23 +121,23 @@ class FirstEntranceTest extends \PHPUnit_Framework_TestCase
      * @param int $countCustomization
      * @return \Magento\Core\Model\Resource\Theme\CollectionFactory
      */
-    protected function _getThemeCollectionFactory($countCustomization)
+    protected function getThemeCollectionFactory($countCustomization)
     {
         $themeCollectionMock = $this->getMockBuilder(
             'Magento\Core\Model\Resource\Theme\Collection'
         )->disableOriginalConstructor()->setMethods(
-                array('addTypeFilter', 'getSize')
-            )->getMock();
+            array('addTypeFilter', 'getSize')
+        )->getMock();
 
         $themeCollectionMock->expects(
             $this->once()
         )->method(
-                'addTypeFilter'
-            )->with(
-                \Magento\Framework\View\Design\ThemeInterface::TYPE_VIRTUAL
-            )->will(
-                $this->returnValue($themeCollectionMock)
-            );
+            'addTypeFilter'
+        )->with(
+            \Magento\Framework\View\Design\ThemeInterface::TYPE_VIRTUAL
+        )->will(
+            $this->returnValue($themeCollectionMock)
+        );
 
         $themeCollectionMock->expects($this->once())->method('getSize')->will($this->returnValue($countCustomization));
 
@@ -155,19 +155,18 @@ class FirstEntranceTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * @covers \Magento\DesignEditor\Controller\Adminhtml\System\Design\Editor::firstEntranceAction
      * @dataProvider firstEntranceActionDataProvider
      */
     public function testFirstEntranceAction($countCustomization)
     {
-        $this->_objectManagerMock->expects(
+        $this->objectManagerMock->expects(
             $this->any()
         )->method(
-                'get'
-            )->will(
-                $this->returnValueMap($this->_getObjectManagerMap($countCustomization))
-            );
-        $this->assertNull($this->_model->execute());
+            'get'
+        )->will(
+            $this->returnValueMap($this->getObjectManagerMap($countCustomization))
+        );
+        $this->assertNull($this->model->execute());
     }
 
     /**
@@ -182,7 +181,7 @@ class FirstEntranceTest extends \PHPUnit_Framework_TestCase
      * @param int $countCustomization
      * @return array
      */
-    protected function _getObjectManagerMap($countCustomization)
+    protected function getObjectManagerMap($countCustomization)
     {
         $translate = $this->getMock('Magento\Framework\TranslateInterface', array(), array(), '', false);
         $translate->expects($this->any())->method('translate')->will($this->returnSelf());
@@ -210,10 +209,10 @@ class FirstEntranceTest extends \PHPUnit_Framework_TestCase
         $backendSession->expects(
             $this->any()
         )->method(
-                'getMessages'
-            )->will(
-                $this->returnValue($this->getMock('Magento\Framework\Message\Collection', array(), array(), '', false))
-            );
+            'getMessages'
+        )->will(
+            $this->returnValue($this->getMock('Magento\Framework\Message\Collection', array(), array(), '', false))
+        );
 
         $inlineMock = $this->getMock('Magento\Framework\Translate\Inline', array(), array(), '', false);
         $aclFilterMock = $this->getMock('Magento\Backend\Model\Layout\Filter\Acl', array(), array(), '', false);
@@ -221,7 +220,7 @@ class FirstEntranceTest extends \PHPUnit_Framework_TestCase
         return array(
             array(
                 'Magento\Core\Model\Resource\Theme\CollectionFactory',
-                $this->_getThemeCollectionFactory($countCustomization)
+                $this->getThemeCollectionFactory($countCustomization)
             ),
             array('Magento\Framework\TranslateInterface', $translate),
             array('Magento\Framework\App\Config\ScopeConfigInterface', $configMock),
diff --git a/dev/tests/unit/testsuite/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/IndexTest.php b/dev/tests/unit/testsuite/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/IndexTest.php
index cba4f9fe60233a8f38f6776eb7c5dbe5b8d05184..39372f5e57276815b0a6016402ff949c36b1bfbd 100644
--- a/dev/tests/unit/testsuite/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/IndexTest.php
+++ b/dev/tests/unit/testsuite/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/IndexTest.php
@@ -32,16 +32,16 @@ class IndexTest extends \PHPUnit_Framework_TestCase
     /**
      * @var \Magento\DesignEditor\Controller\Adminhtml\System\Design\Editor
      */
-    protected $_model;
+    protected $model;
 
     /**
      * @var \PHPUnit_Framework_MockObject_MockObject
      */
-    protected $_objectManagerMock;
+    protected $objectManagerMock;
 
     protected function setUp()
     {
-        $this->_objectManagerMock = $this->getMock('Magento\Framework\ObjectManager');
+        $this->objectManagerMock = $this->getMock('Magento\Framework\ObjectManager');
 
         $request = $this->getMock('Magento\Framework\App\Request\Http', array(), array(), '', false);
         $request->expects($this->any())->method('setActionName')->will($this->returnSelf());
@@ -100,7 +100,7 @@ class IndexTest extends \PHPUnit_Framework_TestCase
             'Magento\DesignEditor\Controller\Adminhtml\System\Design\Editor',
             array(
                 'request' => $request,
-                'objectManager' => $this->_objectManagerMock,
+                'objectManager' => $this->objectManagerMock,
                 'layout' => $layoutMock,
                 'invokeArgs' => array(
                     'helper' => $this->getMock('Magento\Backend\Helper\Data', array(), array(), '', false),
@@ -109,7 +109,7 @@ class IndexTest extends \PHPUnit_Framework_TestCase
             )
         );
 
-        $this->_model = $objectManagerHelper->getObject(
+        $this->model = $objectManagerHelper->getObject(
             'Magento\DesignEditor\Controller\Adminhtml\System\Design\Editor\Index',
             $constructArguments
         );
@@ -121,7 +121,7 @@ class IndexTest extends \PHPUnit_Framework_TestCase
      * @param int $countCustomization
      * @return \Magento\Core\Model\Resource\Theme\CollectionFactory
      */
-    protected function _getThemeCollectionFactory($countCustomization)
+    protected function getThemeCollectionFactory($countCustomization)
     {
         $themeCollectionMock = $this->getMockBuilder(
             'Magento\Core\Model\Resource\Theme\Collection'
@@ -155,19 +155,18 @@ class IndexTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * @covers \Magento\DesignEditor\Controller\Adminhtml\System\Design\Editor::indexAction
      * @dataProvider indexActionDataProvider
      */
     public function testIndexAction($countCustomization)
     {
-        $this->_objectManagerMock->expects(
+        $this->objectManagerMock->expects(
             $this->any()
         )->method(
             'get'
         )->will(
-            $this->returnValueMap($this->_getObjectManagerMap($countCustomization, 'index'))
+            $this->returnValueMap($this->getObjectManagerMap($countCustomization, 'index'))
         );
-        $this->assertNull($this->_model->execute());
+        $this->assertNull($this->model->execute());
     }
 
     /**
@@ -182,7 +181,7 @@ class IndexTest extends \PHPUnit_Framework_TestCase
      * @param int $countCustomization
      * @return array
      */
-    protected function _getObjectManagerMap($countCustomization)
+    protected function getObjectManagerMap($countCustomization)
     {
         $translate = $this->getMock('Magento\Framework\TranslateInterface', array(), array(), '', false);
         $translate->expects($this->any())->method('translate')->will($this->returnSelf());
@@ -221,7 +220,7 @@ class IndexTest extends \PHPUnit_Framework_TestCase
         return array(
             array(
                 'Magento\Core\Model\Resource\Theme\CollectionFactory',
-                $this->_getThemeCollectionFactory($countCustomization)
+                $this->getThemeCollectionFactory($countCustomization)
             ),
             array('Magento\Framework\TranslateInterface', $translate),
             array('Magento\Framework\App\Config\ScopeConfigInterface', $configMock),
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/AbstractTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/AbstractTest.php
index 1718e6be150c71e12e00ed05e64c704b292d8546..c815194b56ba3c18f8f3cc3d1348eb2f6452e903 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/AbstractTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/AbstractTest.php
@@ -31,13 +31,18 @@ class AbstractTest extends \PHPUnit_Framework_TestCase
      */
     protected $_model;
 
+    /** @var  \Magento\Eav\Model\Config */
+    protected $eavConfig;
+
     protected function setUp()
     {
+
+        $this->eavConfig = $this->getMock('Magento\Eav\Model\Config', array(), array(), '', false);
         $this->_model = $this->getMockForAbstractClass(
             'Magento\Eav\Model\Entity\AbstractEntity',
             array(
                 $this->getMock('Magento\Framework\App\Resource', array(), array(), '', false),
-                $this->getMock('Magento\Eav\Model\Config', array(), array(), '', false),
+                $this->eavConfig,
                 $this->getMock('Magento\Eav\Model\Entity\Attribute\Set', array(), array(), '', false),
                 $this->getMock('\Magento\Framework\Locale\FormatInterface'),
                 $this->getMock('Magento\Eav\Model\Resource\Helper', array(), array(), '', false),
@@ -282,32 +287,38 @@ class AbstractTest extends \PHPUnit_Framework_TestCase
         $backendModel->setAttribute($attribute);
 
         $attribute->expects($this->any())->method('getBackend')->will($this->returnValue($backendModel));
+        $attribute->setId(222);
 
         $attributes[$attributeCode] = $attribute;
 
+        $eavConfig = $this->getMockBuilder('Magento\Eav\Model\Config')
+            ->disableOriginalConstructor()
+            ->getMock();
+
         $data = array(
             $this->getMock('Magento\Framework\App\Resource', array(), array(), '', false),
-            $this->getMock('Magento\Eav\Model\Config', array(), array(), '', false),
+            $eavConfig,
             $this->getMock('Magento\Eav\Model\Entity\Attribute\Set', array(), array(), '', false),
             $this->getMock('Magento\Framework\Locale\FormatInterface'),
             $this->getMock('Magento\Eav\Model\Resource\Helper', array(), array(), '', false),
             $this->getMock('Magento\Framework\Validator\UniversalFactory', array(), array(), '', false),
             array('type' => $entityType, 'entityTable' => 'entityTable', 'attributesByCode' => $attributes)
         );
-        /** @var $model \PHPUnit_Framework_MockObject_MockObject */
-        $model = $this->getMockForAbstractClass(
-            'Magento\Eav\Model\Entity\AbstractEntity',
-            $data,
-            '',
-            true,
-            true,
-            true,
-            array('_getValue')
+        /** @var $model \Magento\Framework\Model\AbstractModel|\PHPUnit_Framework_MockObject_MockObject */
+        $model = $this->getMockBuilder('Magento\Eav\Model\Entity\AbstractEntity')
+            ->setConstructorArgs($data)
+            ->setMethods(['_getValue'])
+            ->getMock();
+
+        $model->expects($this->any())->method('_getValue')->will($this->returnValue($eavConfig));
+        $eavConfig->expects($this->any())->method('getAttribute')->will(
+            $this->returnCallback(
+                function ($entityType, $attributeCode) use ($attributes) {
+                    return $entityType && isset($attributes[$attributeCode]) ? $attributes[$attributeCode] : null;
+                }
+            )
         );
 
-        $configMock = $this->getMock('Magento\Eav\Model\Config', array(), array(), '', false);
-        $model->expects($this->any())->method('_getValue')->will($this->returnValue($configMock));
-
         $model->setConnection($this->_getAdapterMock());
         $model->isPartialSave(true);
 
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Attribute/Source/BooleanTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Attribute/Source/BooleanTest.php
index 1eb6d9c32218b2a882261b92d4d3e41da5376a3f..502ce4926bbe73d6b9d88cadfae20edc99b737c1 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Attribute/Source/BooleanTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Attribute/Source/BooleanTest.php
@@ -38,7 +38,7 @@ class BooleanTest extends \PHPUnit_Framework_TestCase
         $this->_model = $objectManager->getObject('Magento\Eav\Model\Entity\Attribute\Source\Boolean');
     }
 
-    public function testGetFlatColums()
+    public function testGetFlatColumns()
     {
         $abstractAttributeMock = $this->getMock(
             '\Magento\Eav\Model\Entity\Attribute\AbstractAttribute',
@@ -52,18 +52,153 @@ class BooleanTest extends \PHPUnit_Framework_TestCase
 
         $this->_model->setAttribute($abstractAttributeMock);
 
-        $flatColums = $this->_model->getFlatColums();
-
-        $this->assertTrue(is_array($flatColums), 'FlatColums must be an array value');
-        $this->assertTrue(!empty($flatColums), 'FlatColums must be not empty');
-        foreach ($flatColums as $result) {
-            $this->assertArrayHasKey('unsigned', $result, 'FlatColums must have "unsigned" column');
-            $this->assertArrayHasKey('default', $result, 'FlatColums must have "default" column');
-            $this->assertArrayHasKey('extra', $result, 'FlatColums must have "extra" column');
-            $this->assertArrayHasKey('type', $result, 'FlatColums must have "type" column');
-            $this->assertArrayHasKey('nullable', $result, 'FlatColums must have "nullable" column');
-            $this->assertArrayHasKey('comment', $result, 'FlatColums must have "comment" column');
-            $this->assertArrayHasKey('length', $result, 'FlatColums must have "length" column');
+        $flatColumns = $this->_model->getFlatColumns();
+
+        $this->assertTrue(is_array($flatColumns), 'FlatColumns must be an array value');
+        $this->assertTrue(!empty($flatColumns), 'FlatColumns must be not empty');
+        foreach ($flatColumns as $result) {
+            $this->assertArrayHasKey('unsigned', $result, 'FlatColumns must have "unsigned" column');
+            $this->assertArrayHasKey('default', $result, 'FlatColumns must have "default" column');
+            $this->assertArrayHasKey('extra', $result, 'FlatColumns must have "extra" column');
+            $this->assertArrayHasKey('type', $result, 'FlatColumns must have "type" column');
+            $this->assertArrayHasKey('nullable', $result, 'FlatColumns must have "nullable" column');
+            $this->assertArrayHasKey('comment', $result, 'FlatColumns must have "comment" column');
+            $this->assertArrayHasKey('length', $result, 'FlatColumns must have "length" column');
+        }
+    }
+
+    /**
+     * @covers \Magento\Eav\Model\Entity\Attribute\Source\Boolean::addValueSortToCollection
+     *
+     * @dataProvider addValueSortToCollectionDataProvider
+     * @param string $direction
+     * @param bool $isScopeGlobal
+     * @param array $expectedJoinCondition
+     * @param string $expectedOrder
+     */
+    public function testAddValueSortToCollection(
+        $direction, $isScopeGlobal, $expectedJoinCondition, $expectedOrder
+    ) {
+        $attributeMock = $this->getAttributeMock();
+        $attributeMock->expects($this->any())->method('isScopeGlobal')->will($this->returnValue($isScopeGlobal));
+
+        $selectMock = $this->getMock('\Magento\Framework\DB\Select', [], [], '', false);
+
+        $collectionMock = $this->getCollectionMock();
+        $collectionMock->expects($this->any())->method('getSelect')->will($this->returnValue($selectMock));
+
+        foreach ($expectedJoinCondition as $step => $data) {
+            $selectMock->expects($this->at($step))->method('joinLeft')
+                ->with($data['requisites'], $data['condition'], [])->will($this->returnSelf());
         }
+
+        $selectMock->expects($this->once())->method('order')->with($expectedOrder);
+
+        $this->_model->setAttribute($attributeMock);
+        $this->_model->addValueSortToCollection($collectionMock, $direction);
+    }
+
+    /**
+     * @return array
+     */
+    public function addValueSortToCollectionDataProvider()
+    {
+        return  [
+            [
+                'direction' => 'ASC',
+                'isScopeGlobal' => false,
+                'expectedJoinCondition' => [
+                    0 => [
+                        'requisites' => ['code_t1' => "table"],
+                        'condition' =>
+                            "e.entity_id=code_t1.entity_id AND code_t1.attribute_id='123' AND code_t1.store_id='0'",
+                    ],
+                    1 => [
+                        'requisites' => ['code_t2' => "table"],
+                        'condition' =>
+                            "e.entity_id=code_t2.entity_id AND code_t2.attribute_id='123' AND code_t2.store_id='12'"
+                    ]
+                ],
+                'expectedOrder' => 'IF(code_t2.value_id > 0, code_t2.value, code_t1.value) ASC',
+            ],
+            [
+                'direction' => 'DESC',
+                'isScopeGlobal' => false,
+                'expectedJoinCondition' => [
+                    0 => [
+                        'requisites' => ['code_t1' => "table"],
+                        'condition' =>
+                            "e.entity_id=code_t1.entity_id AND code_t1.attribute_id='123' AND code_t1.store_id='0'",
+                    ],
+                    1 => [
+                        'requisites' => ['code_t2' => "table"],
+                        'condition' =>
+                            "e.entity_id=code_t2.entity_id AND code_t2.attribute_id='123' AND code_t2.store_id='12'"
+                    ]
+                ],
+                'expectedOrder' => 'IF(code_t2.value_id > 0, code_t2.value, code_t1.value) DESC',
+            ],
+            [
+                'direction' => 'DESC',
+                'isScopeGlobal' => true,
+                'expectedJoinCondition' => [
+                    0 => [
+                        'requisites' => ['code_t' => "table"],
+                        'condition' =>
+                            "e.entity_id=code_t.entity_id AND code_t.attribute_id='123' AND code_t.store_id='0'",
+                    ]
+                ],
+                'expectedOrder' => 'code_t.value DESC',
+            ],
+            [
+                'direction' => 'ASC',
+                'isScopeGlobal' => true,
+                'expectedJoinCondition' => [
+                    0 => [
+                        'requisites' => ['code_t' => "table"],
+                        'condition' =>
+                            "e.entity_id=code_t.entity_id AND code_t.attribute_id='123' AND code_t.store_id='0'",
+                    ]
+                ],
+                'expectedOrder' => 'code_t.value ASC',
+            ],
+        ];
+    }
+
+    /**
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function getCollectionMock()
+    {
+        $collectionMethods = ['getSelect', 'getStoreId', 'getConnection'];
+        $collectionMock = $this->getMock(
+            '\Magento\Eav\Model\Entity\Collection\AbstractCollection', $collectionMethods, [], '', false
+        );
+
+        $connectionMock = $this->getMock('\Magento\Framework\DB\Adapter\Pdo\Mysql', ['method'], [], '', false);
+
+        $collectionMock->expects($this->any())->method('getConnection')->will($this->returnValue($connectionMock));
+        $collectionMock->expects($this->any())->method('getStoreId')->will($this->returnValue('12'));
+
+        return $collectionMock;
+    }
+
+    /**
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function getAttributeMock()
+    {
+        $attributeMockMethods = ['getAttributeCode', 'getId', 'getBackend', 'isScopeGlobal', '__wakeup'];
+        $attributeMock = $this->getMock(
+            '\Magento\Eav\Model\Entity\Attribute\AbstractAttribute', $attributeMockMethods, [], '', false
+        );
+        $backendMock = $this->getMock('\Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend', [], [], '', false);
+
+        $attributeMock->expects($this->any())->method('getAttributeCode')->will($this->returnValue('code'));
+        $attributeMock->expects($this->any())->method('getId')->will($this->returnValue('123'));
+        $attributeMock->expects($this->any())->method('getBackend')->will($this->returnValue($backendMock));
+        $backendMock->expects($this->any())->method('getTable')->will($this->returnValue('table'));
+
+        return $attributeMock;
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Attribute/Source/TableTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Attribute/Source/TableTest.php
index 2d6531d79743a721141f76a972f2fe0f5f8ef8aa..2e26b78c295119b0a1b22dae71453a9a8f627be0 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Attribute/Source/TableTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Attribute/Source/TableTest.php
@@ -38,7 +38,7 @@ class TableTest extends \PHPUnit_Framework_TestCase
         $this->_model = $objectManager->getObject('Magento\Eav\Model\Entity\Attribute\Source\Table');
     }
 
-    public function testGetFlatColums()
+    public function testGetFlatColumns()
     {
         $abstractFrontendMock = $this->getMock(
             'Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend',
@@ -68,19 +68,19 @@ class TableTest extends \PHPUnit_Framework_TestCase
 
         $this->_model->setAttribute($abstractAttributeMock);
 
-        $flatColums = $this->_model->getFlatColums();
+        $flatColumns = $this->_model->getFlatColumns();
 
-        $this->assertTrue(is_array($flatColums), 'FlatColums must be an array value');
-        $this->assertTrue(!empty($flatColums), 'FlatColums must be not empty');
+        $this->assertTrue(is_array($flatColumns), 'FlatColumns must be an array value');
+        $this->assertTrue(!empty($flatColumns), 'FlatColumns must be not empty');
 
-        foreach ($flatColums as $result) {
-            $this->assertArrayHasKey('unsigned', $result, 'FlatColums must have "unsigned" column');
-            $this->assertArrayHasKey('default', $result, 'FlatColums must have "default" column');
-            $this->assertArrayHasKey('extra', $result, 'FlatColums must have "extra" column');
-            $this->assertArrayHasKey('type', $result, 'FlatColums must have "type" column');
-            $this->assertArrayHasKey('nullable', $result, 'FlatColums must have "nullable" column');
-            $this->assertArrayHasKey('comment', $result, 'FlatColums must have "comment" column');
-            $this->assertArrayHasKey('length', $result, 'FlatColums must have "length" column');
+        foreach ($flatColumns as $result) {
+            $this->assertArrayHasKey('unsigned', $result, 'FlatColumns must have "unsigned" column');
+            $this->assertArrayHasKey('default', $result, 'FlatColumns must have "default" column');
+            $this->assertArrayHasKey('extra', $result, 'FlatColumns must have "extra" column');
+            $this->assertArrayHasKey('type', $result, 'FlatColumns must have "type" column');
+            $this->assertArrayHasKey('nullable', $result, 'FlatColumns must have "nullable" column');
+            $this->assertArrayHasKey('comment', $result, 'FlatColumns must have "comment" column');
+            $this->assertArrayHasKey('length', $result, 'FlatColumns must have "length" column');
         }
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Framework/App/Language/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Framework/App/Language/ConfigTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..01cbf21eab5a586600c774b75d589e90e7372a29
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/App/Language/ConfigTest.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\App\Language;
+
+/**
+ * Test for configuration of language
+ */
+class ConfigTest extends \PHPUnit_Framework_TestCase
+{
+    public function testConfiguration()
+    {
+        $languageXml = file_get_contents(__DIR__ . '/_files/language.xml');
+        $languageConfig = new Config($languageXml);
+        $this->assertEquals('en_GB', $languageConfig->getCode());
+        $this->assertEquals('magento', $languageConfig->getVendor());
+        $this->assertEquals('en_gb', $languageConfig->getPackage());
+        $this->assertEquals('100', $languageConfig->getSortOrder());
+        $this->assertEquals(
+            [
+                ['vendor' => 'oxford-university', 'package' => 'en_us'],
+                ['vendor' => 'oxford-university', 'package' => 'en_gb']
+            ],
+            $languageConfig->getUses()
+        );
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/App/Language/DictionaryTest.php b/dev/tests/unit/testsuite/Magento/Framework/App/Language/DictionaryTest.php
index b1b939ae96e84ca5bb9954d31cdd932e2fc0fb27..0ba2fab53d11f985158cc74721c0464611767107 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/App/Language/DictionaryTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/App/Language/DictionaryTest.php
@@ -36,6 +36,11 @@ class DictionaryTest extends \PHPUnit_Framework_TestCase
      */
     private $dir;
 
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $configFactory;
+
     protected function setUp()
     {
         $this->dir = $this->getMockForAbstractClass('\Magento\Framework\Filesystem\Directory\ReadInterface');
@@ -43,99 +48,76 @@ class DictionaryTest extends \PHPUnit_Framework_TestCase
         $filesystem->expects($this->once())
             ->method('getDirectoryRead')
             ->with(\Magento\Framework\App\Filesystem::LOCALE_DIR)
-            ->will($this->returnValue($this->dir))
-        ;
-        $this->model = new Dictionary($filesystem);
+            ->will($this->returnValue($this->dir));
+        $this->configFactory = $this->getMockBuilder('\Magento\Framework\App\Language\ConfigFactory')
+            ->setMethods(['create'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->model = new Dictionary($filesystem, $this->configFactory);
     }
 
-    public function testGetDictionary()
+    /**
+     * @param array $languagesData
+     * @param array $csvMap
+     * @param array $dictionaryMap
+     * @param $languageCode
+     * @param array $expectation
+     * @dataProvider dictionaryDataProvider
+     */
+    public function testDictionaryGetter($languagesData, $csvMap, $dictionaryMap, $languageCode, $expectation)
     {
-        $dir = [
-            'Foo/en_AU/language.xml',
-            'Bar/en_GB/language.xml',
-            'Baz/en_GB/language.xml',
-            'Bar/en_US/language.xml'
-        ];
-        $xmlMap = [
-            [
-                $dir[0],
-                null,
-                null,
-                '<?xml version="1.0"?>
-                <language>
-                    <code>en_AU</code>
-                    <vendor>Foo</vendor>
-                    <use vendor="Bar" code="en_GB"/>
-                    <use vendor="Baz" code="en_GB"/>
-                </language>'
-            ],
-            [
-                $dir[1],
-                null,
-                null,
-                '<?xml version="1.0"?>
-                <language>
-                    <code>en_GB</code>
-                    <vendor>Bar</vendor>
-                    <sort_order>100</sort_order>
-                    <use vendor="Bar" code="en_US"/>
-                </language>'
-            ],
-            [
-                $dir[2],
-                null,
-                null,
-                '<?xml version="1.0"?>
-                <language>
-                    <code>en_GB</code>
-                    <vendor>Baz</vendor>
-                    <sort_order>50</sort_order>
-                </language>'
-            ],
-            [
-                $dir[3],
-                null,
-                null,
-                '<?xml version="1.0"?>
-                <language>
-                    <code>en_US</code>
-                    <vendor>Bar</vendor>
-                </language>'
-            ],
-        ];
-        $csvMap = [
-            ['Bar/en_US/*.csv', null, ['Bar/en_US/b.csv', 'Bar/en_US/a.csv']],
-            ['Baz/en_GB/*.csv', null, ['Baz/en_GB/1.csv']],
-            ['Bar/en_GB/*.csv', null, ['Bar/en_GB/1.csv']],
-            ['Foo/en_AU/*.csv', null, ['Foo/en_AU/1.csv', 'Foo/en_AU/2.csv']],
-        ];
-        $dictionaryMap = [
-            ['Bar/en_US/a.csv', $this->getCsvMock([['one', '1'], ['two', '2']])],
-            ['Bar/en_US/b.csv', $this->getCsvMock([['three', '3'], ['four', '4']])],
-            ['Baz/en_GB/1.csv', $this->getCsvMock([['four and 5/10', '4.5']])],
-            ['Bar/en_GB/1.csv', $this->getCsvMock([['four and 75/100', '4.75'], ['four and 5/10', '4.50']])],
-            ['Foo/en_AU/1.csv', $this->getCsvMock([['one', '1.0'], ['five', '5.0']])],
-            ['Foo/en_AU/2.csv', $this->getCsvMock([['six', '6.0']])],
-        ];
+        $languagePaths = array_keys($languagesData);
         $this->dir->expects($this->any())->method('search')->will($this->returnValueMap(
-            array_merge([['*/*/language.xml', null, $dir]], $csvMap)
+            array_merge([['*/*/language.xml', null, $languagePaths]], $csvMap)
         ));
-        $this->dir->expects($this->any())->method('readFile')->will($this->returnValueMap($xmlMap));
+
+        // Return first argument to mark content for configuration factory mock
+        $this->dir->expects($this->any())->method('readFile')->will($this->returnArgument(0));
+        $configCallback = $this->returnCallback(function ($arguments) use ($languagesData) {
+            return $this->getLanguageConfigMock($languagesData[$arguments['source']]);
+        });
+        $this->configFactory->expects($this->any())->method('create')->will($configCallback);
+
+        // Covers data from dataProvider
+        $dictionaryMap = array_map(function ($data) {
+            list($path, $result) = $data;
+            return [$path, $this->getCsvMock($result)];
+        }, $dictionaryMap);
         $this->dir->expects($this->any())->method('openFile')->will($this->returnValueMap($dictionaryMap));
-        $result = $this->model->getDictionary('en_AU');
-        $this->assertSame(
-            [
-                'one' => '1.0',
-                'two' => '2',
-                'three' => '3',
-                'four' => '4',
-                'four and 5/10' => '4.50',
-                'four and 75/100' => '4.75',
-                'five' => '5.0',
-                'six' => '6.0'
-            ],
-            $result
-        );
+
+        $result = $this->model->getDictionary($languageCode);
+        $this->assertSame($expectation, $result);
+    }
+
+    public function dictionaryDataProvider()
+    {
+        return [
+            // First case with multiple inheritance, the obtained dictionary is en_AU
+            'a case with multiple inheritance' => $this->getDataMultipleInheritance(),
+            // Second case with inheritance of package with the same language code
+            'a case with inheritance similar language code' => $this->getDataInheritanceWitSimilarCode(),
+            // Third case with circular inheritance, when two packages depend on each other
+            'a case with circular inheritance' => $this->getDataCircularInheritance()
+        ];
+    }
+
+    /**
+     * Create mock of language configuration model
+     *
+     * @param array $languageData
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    private function getLanguageConfigMock($languageData)
+    {
+        $languageConfig = $this->getMock('\Magento\Framework\App\Language\Config', [], [], '', false);
+        $languageConfig->expects($this->any())->method('getCode')->will($this->returnValue($languageData['code']));
+        $languageConfig->expects($this->any())->method('getVendor')->will($this->returnValue($languageData['vendor']));
+        $languageConfig->expects($this->any())->method('getPackage')
+            ->will($this->returnValue($languageData['package']));
+        $languageConfig->expects($this->any())->method('getSortOrder')
+            ->will($this->returnValue($languageData['sort_order']));
+        $languageConfig->expects($this->any())->method('getUses')->will($this->returnValue($languageData['use']));
+        return $languageConfig;
     }
 
     /**
@@ -153,4 +135,169 @@ class DictionaryTest extends \PHPUnit_Framework_TestCase
         $file->expects($this->at($i))->method('readCsv')->will($this->returnValue(false));
         return $file;
     }
+
+    /**
+     * @return array
+     */
+    private function getDataMultipleInheritance()
+    {
+        return [
+            'languages' => [
+                'foo/en_au/language.xml' => [
+                    'code' => 'en_AU',
+                    'vendor' => 'foo',
+                    'package' => 'en_au',
+                    'sort_order' => 0,
+                    'use' => [
+                        ['vendor' => 'bar', 'package' => 'en_gb'],
+                        ['vendor' => 'baz', 'package' => 'en_gb'],
+                    ]
+                ],
+                'bar/en_gb/language.xml' => [
+                    'code' => 'en_GB',
+                    'vendor' => 'bar',
+                    'package' => 'en_gb',
+                    'sort_order' => 100,
+                    'use' => [
+                        ['vendor' => 'bar', 'package' => 'en_us'],
+                    ]
+                ],
+                'baz/en_gb/language.xml' => [
+                    'code' => 'en_GB',
+                    'vendor' => 'baz',
+                    'package' => 'en_gb',
+                    'sort_order' => 50,
+                    'use' => []
+                ],
+                'bar/en_us/language.xml' => [
+                    'code' => 'en_US',
+                    'vendor' => 'bar',
+                    'package' => 'en_us',
+                    'sort_order' => 0,
+                    'use' => []
+                ]
+            ],
+            // ValueMap for \Magento\Framework\Filesystem\Directory\ReadInterface::search($pattern, $path = null)
+            'csv_map' => [
+                ['bar/en_us/*.csv', null, ['bar/en_us/b.csv', 'bar/en_us/a.csv']],
+                ['baz/en_gb/*.csv', null, ['baz/en_gb/1.csv']],
+                ['bar/en_gb/*.csv', null, ['bar/en_gb/1.csv']],
+                ['foo/en_au/*.csv', null, ['foo/en_au/1.csv', 'foo/en_au/2.csv']],
+            ],
+            // ValueMap for \Magento\Framework\Filesystem\Directory\ReadInterface::openFile($path)
+            'dictionary_map' => [
+                ['bar/en_us/a.csv', [['one', '1'], ['two', '2']]],
+                ['bar/en_us/b.csv', [['three', '3'], ['four', '4']]],
+                ['baz/en_gb/1.csv', [['four and 5/10', '4.5']]],
+                ['bar/en_gb/1.csv', [['four and 75/100', '4.75'], ['four and 5/10', '4.50']]],
+                ['foo/en_au/1.csv', [['one', '1.0'], ['five', '5.0']]],
+                ['foo/en_au/2.csv', [['six', '6.0']]]
+            ],
+            // Dictionary that will be requested
+            'language_code' => 'en_AU',
+            // Expected merged dictionary data
+            'expectation' => [
+                'one' => '1.0',
+                'two' => '2',
+                'three' => '3',
+                'four' => '4',
+                'four and 5/10' => '4.50',
+                'four and 75/100' => '4.75',
+                'five' => '5.0',
+                'six' => '6.0'
+            ]
+        ];
+    }
+
+    /**
+     * @return array
+     */
+    private function getDataInheritanceWitSimilarCode()
+    {
+        return [
+            'languages' => [
+                'theirs/ru_ru/language.xml' => [
+                    'code' => 'ru_RU',
+                    'vendor' => 'theirs',
+                    'package' => 'ru_ru',
+                    'sort_order' => 0,
+                    'use' => []
+                ],
+                'my/ru_ru/language.xml' => [
+                    'code' => 'ru_RU',
+                    'vendor' => 'my',
+                    'package' => 'ru_ru',
+                    'sort_order' => 100,
+                    'use' => [
+                        ['vendor' => 'theirs', 'package' => 'ru_ru'],
+                    ]
+                ],
+            ],
+            // ValueMap for \Magento\Framework\Filesystem\Directory\ReadInterface::search($pattern, $path = null)
+            'csv_map' => [
+                ['theirs/ru_ru/*.csv', null, ['theirs/ru_ru/1.csv']],
+                ['my/ru_ru/*.csv', null, ['my/ru_ru/1.csv']],
+            ],
+            // ValueMap for \Magento\Framework\Filesystem\Directory\ReadInterface::openFile($path)
+            'dictionary_map' => [
+                ['theirs/ru_ru/1.csv', [['one', '1'], ['two', '2']]],
+                ['my/ru_ru/1.csv', [['three', '3'], ['one', '1.0']]],
+            ],
+            // Dictionary that will be requested
+            'language_code' => 'ru_RU',
+            // Expected merged dictionary data
+            'expectation' => [
+                'one' => '1.0',
+                'two' => '2',
+                'three' => '3',
+            ]
+        ];
+    }
+
+    /**
+     * @return array
+     */
+    private function getDataCircularInheritance()
+    {
+        return [
+            'languages' => [
+                'first/en_us/language.xml' => [
+                    'code' => 'en_US',
+                    'vendor' => 'first',
+                    'package' => 'en_us',
+                    'sort_order' => 0,
+                    'use' => [
+                        ['vendor' => 'second', 'package' => 'en_gb']
+                    ]
+                ],
+                'second/en_gb/language.xml' => [
+                    'code' => 'en_GB',
+                    'vendor' => 'second',
+                    'package' => 'en_gb',
+                    'sort_order' => 0,
+                    'use' => [
+                        ['vendor' => 'first', 'package' => 'en_us'],
+                    ]
+                ],
+            ],
+            // ValueMap for \Magento\Framework\Filesystem\Directory\ReadInterface::search($pattern, $path = null)
+            'csv_map' => [
+                ['first/en_us/*.csv', null, ['first/en_us/1.csv']],
+                ['second/en_gb/*.csv', null, ['second/en_gb/1.csv']],
+            ],
+            // ValueMap for \Magento\Framework\Filesystem\Directory\ReadInterface::openFile($path)
+            'dictionary_map' => [
+                ['first/en_us/1.csv', [['three', '3'], ['one', '1.0']]],
+                ['second/en_gb/1.csv', [['one', '1'], ['two', '2']]],
+            ],
+            // Dictionary that will be requested
+            'language_code' => 'en_US',
+            // Expected merged dictionary data
+            'expectation' => [
+                'one' => '1.0',
+                'two' => '2',
+                'three' => '3',
+            ]
+        ];
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Framework/App/Language/_files/language.xml b/dev/tests/unit/testsuite/Magento/Framework/App/Language/_files/language.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f438fb45df49191953caf569f9ecaf7587a71368
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/App/Language/_files/language.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
+    <code>en_GB</code>
+    <vendor>magento</vendor>
+    <package>en_gb</package>
+    <sort_order>100</sort_order>
+    <use vendor="oxford-university" package="en_us"/>
+    <use vendor="oxford-university" package="en_gb"/>
+</language>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Data/FormTest.php b/dev/tests/unit/testsuite/Magento/Framework/Data/FormTest.php
index fe9ecdb6f425748129db6dd82181d17524f9852b..1c6c0a812afba8fcce5f4950c6805c04c52c928d 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Data/FormTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Data/FormTest.php
@@ -44,15 +44,6 @@ class FormTest extends \PHPUnit_Framework_TestCase
      */
     protected $_formKeyMock;
 
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $elementMock;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $allElementsMock;
     /**
      * @var \Magento\Framework\Data\Form
      */
@@ -62,11 +53,12 @@ class FormTest extends \PHPUnit_Framework_TestCase
     {
         $this->_factoryElementMock = $this->getMock(
             'Magento\Framework\Data\Form\Element\Factory',
-            array('create'),
+            array(),
             array(),
             '',
             false
         );
+
         $this->_factoryCollectionMock = $this->getMock(
             'Magento\Framework\Data\Form\Element\CollectionFactory',
             array('create'),
@@ -74,8 +66,16 @@ class FormTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->allElementsMock =
-            $this->getMock('Magento\Framework\Data\Form\Element\Collection', [], [], '', false);
+
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $collectionModel = $objectManager->getObject
+            ('Magento\Framework\Data\Form\Element\Collection');
+
+        $this->_factoryCollectionMock
+            ->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($collectionModel));
+
         $this->_formKeyMock = $this->getMock(
             'Magento\Framework\Data\Form\FormKey',
             array('getFormKey'),
@@ -83,19 +83,12 @@ class FormTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $methods = ['getId', 'setValue', 'setName', 'getName', '_wakeup'];
-        $this->elementMock =
-            $this->getMock('Magento\Framework\Data\Form\Element\AbstractElement', $methods, [], '', false);
 
         $this->_form = new Form($this->_factoryElementMock, $this->_factoryCollectionMock, $this->_formKeyMock);
     }
 
     public function testFormKeyUsing()
     {
-        $this->_factoryCollectionMock
-            ->expects($this->any())
-            ->method('create')
-            ->will($this->returnValue(array()));
         $formKey = 'form-key';
         $this->_formKeyMock->expects($this->once())->method('getFormKey')->will($this->returnValue($formKey));
 
@@ -104,74 +97,86 @@ class FormTest extends \PHPUnit_Framework_TestCase
         $this->assertContains($formKey, $this->_form->toHtml());
     }
 
-    public function testAddValue()
+    public function testSettersGetters()
     {
-        $this->_factoryCollectionMock
-            ->expects($this->once())
-            ->method('create')
-            ->will($this->returnValue($this->allElementsMock));
-        $this->_form = new Form($this->_factoryElementMock, $this->_factoryCollectionMock, $this->_formKeyMock);
-        $values = [
-            'element_id' => 'value_one'
-        ];
-        $this->elementMock->expects($this->once())->method('getId')->will($this->returnValue('element_id'));
-        $this->allElementsMock->expects($this->once())->method('add')->with($this->elementMock);
-        $this->elementMock->expects($this->once())->method('setValue')->with('value_one');
-        $this->_form->addElementToCollection($this->elementMock);
-        $this->_form->addValues($values);
+        $setElementRenderer = $this->getMockBuilder
+            ('Magento\Backend\Block\Widget\Form\Renderer\Element')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        // note: this results in setting a static variable in the Form class
+        $this->_form->setElementRenderer($setElementRenderer);
+        $getElementRenderer = $this->_form->getElementRenderer();
+        $this->assertSame($setElementRenderer, $getElementRenderer);
+        // restore our Form to its earlier state
+        $this->_form->setElementRenderer(null);
+
+
+        $setFieldsetRenderer = $this->getMockBuilder
+            ('Magento\Backend\Block\Widget\Form\Renderer\Fieldset')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->_form->setFieldsetRenderer($setFieldsetRenderer);
+        $getFieldsetRenderer = $this->_form->getFieldsetRenderer();
+        $this->assertSame($setFieldsetRenderer, $getFieldsetRenderer);
+
+
+        $setFieldsetElementRenderer = $this->getMockBuilder
+            ('Magento\Backend\Block\Widget\Form\Renderer\Fieldset')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->_form->setFieldsetElementRenderer($setFieldsetElementRenderer);
+        $getFieldsetElementRenderer = $this->_form->getFieldsetElementRenderer();
+        $this->assertSame($setFieldsetElementRenderer, $getFieldsetElementRenderer);
+
+        $this->assertSame($this->_form->getHtmlAttributes(), ['id', 'name', 'method',
+            'action', 'enctype', 'class', 'onsubmit', 'target']);
+
+        $this->_form->setFieldContainerIdPrefix('abc');
+        $this->assertSame($this->_form->getFieldContainerIdPrefix(), 'abc');
+
+        $result = $this->_form->addSuffixToName('123', 'abc');
+        $this->assertSame($result, 'abc[123]');
     }
 
     /**
-     * @param int $number
-     * @param string $elementId
-     * @param string|null $value
-     *
-     * @dataProvider setValueDataProvider
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage Element with id "1" already exists
      */
-    public function testSetValue($number, $elementId, $value)
+    public function testElementExistsException()
     {
-        $this->_factoryCollectionMock
-            ->expects($this->once())
-            ->method('create')
-            ->will($this->returnValue(array($this->elementMock)));
-        $this->_form = new Form($this->_factoryElementMock, $this->_factoryCollectionMock, $this->_formKeyMock);
-        $values = [
-            'element_two' => 'value_two'
-        ];
-        $this->elementMock->expects($this->exactly($number))->method('getId')->will($this->returnValue($elementId));
-        $this->elementMock->expects($this->once())->method('setValue')->with($value);
-        $this->_form->setValues($values);
-    }
+        $buttonElement = $this->getMockBuilder
+            ('Magento\Framework\Data\Form\Element\Button')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $buttonElement->expects($this->any())->method('getId')->will($this->returnValue('1'));
 
-    public function setValueDataProvider()
-    {
-        return [
-            'value_exists' => [2, 'element_two', 'value_two'],
-            'value_not_exist' => [1, 'element_one', null]
-        ];
-    }
+        $this->_form->addElement($buttonElement);
+        $this->_form->addElementToCollection($buttonElement);
 
-    public function testAddFieldNameSuffix()
-    {
-        $this->_factoryCollectionMock
-            ->expects($this->once())
-            ->method('create')
-            ->will($this->returnValue(array($this->elementMock)));
-        $this->_form = new Form($this->_factoryElementMock, $this->_factoryCollectionMock, $this->_formKeyMock);
-        $this->elementMock->expects($this->once())->method('getName')->will($this->returnValue('name'));
-        $this->elementMock->expects($this->once())->method('setName')->with('_suffix[name]');
-        $this->_form->addFieldNameSuffix('_suffix');
+        $this->_form->checkElementId($buttonElement->getId());
     }
 
-    public function testAddEllement()
+    public function testElementOperations()
     {
-        $this->_factoryCollectionMock
-            ->expects($this->any())
-            ->method('create')
-            ->will($this->returnValue($this->allElementsMock));
-        $this->_form = new Form($this->_factoryElementMock, $this->_factoryCollectionMock, $this->_formKeyMock);
-        $this->elementMock->expects($this->any())->method('getId')->will($this->returnValue('element_id'));
-        $this->allElementsMock->expects($this->exactly(2))->method('add')->with($this->elementMock, false);
-        $this->_form->addElement($this->elementMock);
+        $buttonElement = $this->getMockBuilder
+            ('Magento\Framework\Data\Form\Element\Button')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $buttonElement->expects($this->any())->method('getId')->will($this->returnValue('1'));
+        $buttonElement->expects($this->any())->method('getName')->will($this->returnValue('Hero'));
+
+        $this->_form->addElement($buttonElement);
+        $this->_form->addElementToCollection($buttonElement);
+
+        $this->_form->addValues(['1', '2', '3']);
+        $this->_form->setValues(['4', '5', '6']);
+
+        $this->_form->addFieldNameSuffix('abc123');
+
+        $this->_form->removeField($buttonElement->getId());
+        $this->assertSame($this->_form->checkElementId($buttonElement->getId()), true);
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Data/Tree/Node/CollectionTest.php b/dev/tests/unit/testsuite/Magento/Framework/Data/Tree/Node/CollectionTest.php
index afe8ae8c7df5a0a263fc21ce283ecf9f0e10d2c7..3b342a2b1fdb911e81629b023aac5e6959d11207 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Data/Tree/Node/CollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Data/Tree/Node/CollectionTest.php
@@ -31,43 +31,77 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
      */
     protected $collection;
 
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $containerMock;
+    public function setUp()
+    {
+        $tree = new \Magento\Framework\Data\Tree();
+        $node = new \Magento\Framework\Data\Tree\Node(['id' => 'root'], 'id', $tree);
+        $this->collection = new Collection($node);
+    }
 
-    protected function setUp()
+    public function testAdd()
     {
-        $this->containerMock = $this->getMock('Magento\Framework\Data\Tree\Node', [], [], '', false);
-        $this->collection = new \Magento\Framework\Data\Tree\Node\Collection($this->containerMock);
+        $tree = new \Magento\Framework\Data\Tree();
+        $this->assertSame($this->collection->count(), 0);
+        $node = new \Magento\Framework\Data\Tree\Node(['id' => 'node1'], 'id', $tree);
+        $this->collection->add($node);
+        $this->assertSame($this->collection->count(), 1);
     }
 
-    /**
-     * @param int $number
-     * @param \PHPUnit_Framework_MockObject_MockObject|null $returnValue
-     *
-     * @dataProvider testAddDataProvider
-     */
-    public function testAdd($number, $returnValue)
+    public function testOffsets()
+    {
+        $tree = new \Magento\Framework\Data\Tree();
+        $this->assertSame($this->collection->count(), 0);
+        $node = new \Magento\Framework\Data\Tree\Node(['id' => 'node1'], 'id', $tree);
+        $this->collection->add($node);
+        $this->assertSame($this->collection->offsetExists('node1'), true);
+        $this->collection->offsetSet('node1', 'Hello');
+        $this->assertSame($this->collection->offsetExists('node1'), true);
+        $this->assertSame($this->collection->offsetGet('node1'), 'Hello');
+        $this->collection->offsetUnset('node1');
+        $this->assertSame($this->collection->offsetExists('node1'), false);
+    }
+
+    public function testDelete()
     {
-        $nodeMock = $this->getMock('Magento\Framework\Data\Tree\Node', [], [], '', false);
-        $nodeMock->expects($this->once())->method('setParent')->with($this->containerMock);
-        $this->containerMock
-            ->expects($this->exactly($number))
-            ->method('getTree')
-            ->will($this->returnValue($returnValue));
-        $nodeMock->expects($this->once())->method('getId')->will($this->returnValue('id_node'));
-        $this->assertEquals($nodeMock, $this->collection->add($nodeMock));
-        $this->assertEquals(['id_node' => $nodeMock], $this->collection->getNodes());
-        $this->assertEquals($nodeMock, $this->collection->searchById('id_node'));
-        $this->assertEquals(null, $this->collection->searchById('id_node_new'));
+        $tree = new \Magento\Framework\Data\Tree();
+        $this->assertSame($this->collection->count(), 0);
+        $node = new \Magento\Framework\Data\Tree\Node(['id' => 'node1'], 'id', $tree);
+        $this->collection->add($node);
+        $this->assertSame($this->collection->count(), 1);
+        $this->collection->delete($node);
+        $this->assertSame($this->collection->count(), 0);
     }
 
-    public function testAddDataProvider()
+    public function testLastNode()
     {
-        return [
-            'tree_exists' => [2, $this->getMock('Magento\Framework\Data\Tree', [], [], '', false)],
-            'tree_not_exist' => [1, null]
-        ];
+        $tree = new \Magento\Framework\Data\Tree();
+        $node1 = new \Magento\Framework\Data\Tree\Node(['id' => 'node1'], 'id', $tree);
+        $this->collection->add($node1);
+        $node2 = new \Magento\Framework\Data\Tree\Node(['id' => 'node2'], 'id', $tree);
+        $this->collection->add($node2);
+        $this->assertSame($this->collection->lastNode(), $node2);
+        $node3 = new \Magento\Framework\Data\Tree\Node(['id' => 'node3'], 'id', $tree);
+        $this->collection->add($node3);
+
+        $this->assertSame($this->collection->lastNode(), $node3);
+        $this->assertSame($this->collection->lastNode(), $node3);
+        $this->collection->delete($node3);
+        $this->assertSame($this->collection->lastNode(), $node2);
+        $this->assertSame($this->collection->lastNode(), $node2);
+    }
+
+    public function testSearchById()
+    {
+        $tree = new \Magento\Framework\Data\Tree();
+        $node1 = new \Magento\Framework\Data\Tree\Node(['id' => 'node1'], 'id', $tree);
+        $this->collection->add($node1);
+        $node2 = new \Magento\Framework\Data\Tree\Node(['id' => 'node2'], 'id', $tree);
+        $this->collection->add($node2);
+        $this->assertSame($this->collection->lastNode(), $node2);
+        $node3 = new \Magento\Framework\Data\Tree\Node(['id' => 'node3'], 'id', $tree);
+        $this->collection->add($node3);
+
+        $this->assertSame($this->collection->searchById('node2'), $node2);
     }
 }
+ 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Data/TreeTest.php b/dev/tests/unit/testsuite/Magento/Framework/Data/TreeTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e1080d1e801a5a0b438f5498e13aecc4f5832e17
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Data/TreeTest.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\Data;
+
+/**
+ * Tests for \Magento\Framework\Data\FormFactory
+ * @SuppressWarnings(PHPMD.LongVariable)
+ */
+class TreeTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\Data\Tree
+     */
+    protected $_tree;
+
+    public function setUp()
+    {
+        $this->_tree = new Tree();
+    }
+
+    public function testTreeOperations()
+    {
+        $newNode1 = new Tree\Node('abc', 'node1', $this->_tree);
+        $this->_tree->addNode($newNode1);
+        $newNode2 = new Tree\Node('def', 'node2', $this->_tree);
+        $this->_tree->addNode($newNode2, $newNode1);
+        $newNode3 = new Tree\Node('ghi', 'node3', $this->_tree);
+        $this->_tree->addNode($newNode3, $newNode1);
+        $data1 = ['j', 'k', 'l'];
+        $this->_tree->appendChild($data1, $newNode3);
+        $newNode4 = new Tree\Node('mno', 'node4', $this->_tree);
+        $this->_tree->appendChild($newNode4, $newNode3);
+
+        $this->_tree->removeNode($newNode4);
+        $this->_tree->removeNode($newNode3);
+        $this->_tree->removeNode($newNode2);
+        $this->_tree->removeNode($newNode1);
+
+        $this->assertEmpty($this->_tree->getNodes()->getNodes());
+    }
+}
+ 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Framework/File/CsvTest.php b/dev/tests/unit/testsuite/Magento/Framework/File/CsvTest.php
index c11e537bd3317bc768ea00f7adc42b83b7e5ad08..3993209ca419193d5a1c6e6e98a9afcb1bbea77e 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/File/CsvTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/File/CsvTest.php
@@ -70,11 +70,11 @@ class CsvTest extends \PHPUnit_Framework_TestCase
 
     /**
      * @expectedException \Exception
-     * @expectedExceptionMessage File "FileName" do not exists
+     * @expectedExceptionMessage File "FileNameThatShouldNotExist" do not exists
      */
     public function testGetDataFileNonExistent()
     {
-        $file = 'FileName';
+        $file = 'FileNameThatShouldNotExist';
         $this->_model->getData($file);
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Framework/HTTP/Adapter/CurlTest.php b/dev/tests/unit/testsuite/Magento/Framework/HTTP/Adapter/CurlTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c4d16ea847892c2e52438afcc5877605a5fdfc0b
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/HTTP/Adapter/CurlTest.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\HTTP\Adapter;
+
+class CurlTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var Curl */
+    protected $model;
+
+    /** @var \Closure */
+    public static $curlExectClosure;
+
+    protected function setUp()
+    {
+        $this->model = new \Magento\Framework\HTTP\Adapter\Curl();
+    }
+
+    /**
+     * @param string $response
+     * @dataProvider readDataProvider
+     */
+    public function testRead($response)
+    {
+        self::$curlExectClosure = function () use ($response) {
+            return $response;
+        };
+        $this->assertEquals(file_get_contents(__DIR__ . '/_files/curl_response_expected.txt'), $this->model->read());
+    }
+
+    public function readDataProvider()
+    {
+        return [
+            [file_get_contents(__DIR__ . '/_files/curl_response1.txt')],
+            [file_get_contents(__DIR__ . '/_files/curl_response2.txt')],
+        ];
+    }
+}
+
+/**
+ * Override global PHP function
+ *
+ * @SuppressWarnings("unused")
+ * @param mixed $resource
+ * @return string
+ */
+function curl_exec($resource)
+{
+    return call_user_func(CurlTest::$curlExectClosure);
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/HTTP/Adapter/_files/curl_response1.txt b/dev/tests/unit/testsuite/Magento/Framework/HTTP/Adapter/_files/curl_response1.txt
new file mode 100644
index 0000000000000000000000000000000000000000..74ebfb7b1b5b59a1c31e5bcf7e263c4505a5d3d5
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/HTTP/Adapter/_files/curl_response1.txt
@@ -0,0 +1,24 @@
+HTTP/1.1 100 Continue
+Set-Cookie: ...
+
+HTTP/1.1 100 Continue
+Set-Cookie: ...
+
+HTTP/1.1 101 Continue
+Set-Cookie: ...
+
+HTTP/1.1 100 Continue
+Set-Cookie: ...
+
+HTTP/1.1 200 OK
+Server: Apache
+X-Frame-Options: SAMEORIGIN
+Strict-Transport-Security: max-age=14400
+Strict-Transport-Security: max-age=14400
+Content-Type: text/html; charset=UTF-8
+Date: Mon, 22 Apr 2013 09:52:36 GMT
+Content-Length: 8
+Connection: keep-alive
+Set-Cookie: ...
+
+VERIFIED
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Framework/HTTP/Adapter/_files/curl_response2.txt b/dev/tests/unit/testsuite/Magento/Framework/HTTP/Adapter/_files/curl_response2.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a35904eb08dbcd82bcdc5042a2b6e061b6e6c143
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/HTTP/Adapter/_files/curl_response2.txt
@@ -0,0 +1,12 @@
+HTTP/1.1 200 OK
+Server: Apache
+X-Frame-Options: SAMEORIGIN
+Strict-Transport-Security: max-age=14400
+Strict-Transport-Security: max-age=14400
+Content-Type: text/html; charset=UTF-8
+Date: Mon, 22 Apr 2013 09:52:36 GMT
+Content-Length: 8
+Connection: keep-alive
+Set-Cookie: ...
+
+VERIFIED
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Framework/HTTP/Adapter/_files/curl_response_expected.txt b/dev/tests/unit/testsuite/Magento/Framework/HTTP/Adapter/_files/curl_response_expected.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a35904eb08dbcd82bcdc5042a2b6e061b6e6c143
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/HTTP/Adapter/_files/curl_response_expected.txt
@@ -0,0 +1,12 @@
+HTTP/1.1 200 OK
+Server: Apache
+X-Frame-Options: SAMEORIGIN
+Strict-Transport-Security: max-age=14400
+Strict-Transport-Security: max-age=14400
+Content-Type: text/html; charset=UTF-8
+Date: Mon, 22 Apr 2013 09:52:36 GMT
+Content-Length: 8
+Connection: keep-alive
+Set-Cookie: ...
+
+VERIFIED
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Phrase/Renderer/TranslateTest.php b/dev/tests/unit/testsuite/Magento/Framework/Phrase/Renderer/TranslateTest.php
index e614b0342818ca85c86da696b3ee5d24b68aad89..09f9e16065ba4e969368713c6648c880d403d78c 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Phrase/Renderer/TranslateTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Phrase/Renderer/TranslateTest.php
@@ -26,7 +26,7 @@ namespace Magento\Framework\Phrase\Renderer;
 class TranslateTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Framework\Translate|PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\Translate|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $_translator;
 
@@ -46,44 +46,17 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
         );
     }
 
-    public function testRenderByCode()
+    public function testRender()
     {
-        $text = 'original text';
-        $result = 'rendered text';
+        $text = 'text';
+        $translatedText = 'translated text';
+        $translate = 'translate';
 
-        $this->_translator->expects(
-            $this->once()
-        )->method(
-            'getTheme'
-        )->will(
-            $this->returnValue('theme')
-        );
-        $this->_translator->expects(
-            $this->once()
-        )->method(
-            'getData'
-        )->will(
-            $this->returnValue(['theme::' . $text => $result])
-        );
-
-        $this->assertEquals($result, $this->_renderer->render([$text], []));
-    }
-
-    public function testRenderByText()
-    {
-        $text = 'original text';
-        $result = 'rendered text';
-
-        $this->_translator->expects($this->once())
-            ->method('getTheme')
-            ->will($this->returnValue('theme'));
-        $this->_translator->expects($this->once())
+        $this->_translator->expects($this->exactly(2))
             ->method('getData')
-            ->will($this->returnValue([
-                'theme::' . $text => $result,
-                $text => $result,
-            ]));
+            ->will($this->returnValue([$translatedText => $translate]));
 
-        $this->assertEquals($result, $this->_renderer->render([$text], []));
+        $this->assertEquals($translate, $this->_renderer->render([$translatedText], []));
+        $this->assertEquals($text, $this->_renderer->render([$text], []));
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Simplexml/Config/Cache/AbstractCacheTest.php b/dev/tests/unit/testsuite/Magento/Framework/Simplexml/Config/Cache/AbstractCacheTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d291a1166dba3b8342c1d3f6c65d881ccea81929
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Simplexml/Config/Cache/AbstractCacheTest.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\Simplexml\Config\Cache;
+
+class AbstractCacheTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var File */
+    protected $cache;
+
+    protected $file;
+
+    protected function setUp()
+    {
+        $this->cache = new File();
+        $this->file = realpath(__DIR__ . '/../../_files/data.xml');
+    }
+
+    public function testAddComponent()
+    {
+        $this->cache->addComponent('wrong_path');
+        $this->assertSame([], $this->cache->getComponents());
+
+        $this->cache->addComponent($this->file);
+        $this->assertSame([$this->file => ['mtime' => filemtime($this->file)]], $this->cache->getComponents());
+    }
+
+    public function testValidateComponents()
+    {
+        $this->assertSame(false, $this->cache->validateComponents([]));
+        $this->assertSame(false, $this->cache->validateComponents(''));
+        $this->assertSame(false, $this->cache->validateComponents([$this->file => ['mtime' => '']]));
+        $this->assertSame(false, $this->cache->validateComponents([$this->file => ['mtime' => 1]]));
+        $this->assertSame(true, $this->cache->validateComponents([$this->file => ['mtime' => filemtime($this->file)]]));
+    }
+
+    public function testGetComponentsHash()
+    {
+        $this->cache->addComponent($this->file);
+        $this->assertSame(md5(filemtime($this->file) . ':'), $this->cache->getComponentsHash());
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Simplexml/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Framework/Simplexml/ConfigTest.php
index dce22beb0ad65e102fe9e658ccc867f3cec98f1b..77a9cbd11c384f56ff5f72c2682c64395ce3e889 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Simplexml/ConfigTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Simplexml/ConfigTest.php
@@ -25,12 +25,213 @@ namespace Magento\Framework\Simplexml;
 
 class ConfigTest extends \PHPUnit_Framework_TestCase
 {
+    /**
+     * @var Config
+     */
+    protected $config;
+
+    protected function setUp()
+    {
+        $this->config = new Config();
+    }
+
+    public function testConstruct()
+    {
+        $xml = '<root><node1><node2/></node1><node3><node4/></node3></root>';
+        $file = __DIR__ . '/_files/data.xml';
+
+        $config = new Config($xml);
+        $this->assertXmlStringEqualsXmlString($xml, $config->getXmlString());
+
+        $config = new Config($file);
+        $this->assertXmlStringEqualsXmlString($xml, $config->getXmlString());
+
+        /** @var Element $simpleXml */
+        $simpleXml = simplexml_load_string(file_get_contents($file), 'Magento\Framework\Simplexml\Element');
+        $config = new Config($simpleXml);
+        $this->assertXmlStringEqualsXmlString($xml, $config->getXmlString());
+    }
+
     public function testLoadString()
     {
         $xml = '<?xml version="1.0"?><config><node>1</node></config>';
-        $config = new \Magento\Framework\Simplexml\Config();
-        $this->assertFalse($config->loadString(''));
-        $this->assertTrue($config->loadString($xml));
-        $this->assertXmlStringEqualsXmlString($xml, $config->getXmlString());
+        $this->assertFalse($this->config->loadString(''));
+        $this->assertTrue($this->config->loadString($xml));
+        $this->assertXmlStringEqualsXmlString($xml, $this->config->getXmlString());
+        $this->setExpectedException(
+            'PHPUnit_Framework_Error_Warning',
+            'simplexml_load_string(): Entity: line 1: parser error : Start tag expected,'
+        );
+        $this->assertFalse($this->config->loadString('wrong_path'));
+    }
+
+    public function testLoadDom()
+    {
+        $this->config->loadString('<?xml version="1.0"?><config><node>1</node></config>');
+        $this->assertTrue($this->config->loadDom($this->config->getNode()));
+    }
+
+    public function testGetNode()
+    {
+        $this->assertFalse($this->config->getNode());
+        $config = new Config(__DIR__ . '/_files/mixed_data.xml');
+        $this->assertSame('Value 2.1', $config->getNode('node_2/node_2_1')->asArray());
+    }
+
+    public function testGetXpath()
+    {
+        $this->assertFalse($this->config->getXpath('wrong_xpath'));
+        $config = new Config(__DIR__ . '/_files/mixed_data.xml');
+        $this->assertFalse($config->getXpath('wrong_xpath'));
+        $element = $config->getXpath('/root/node_2/node_2_1');
+        $this->assertArrayHasKey(0, $element);
+        $this->assertInstanceOf('Magento\Framework\Simplexml\Element', $element[0]);
+        $this->assertSame('Value 2.1', $element[0]->asArray());
+    }
+
+    public function testLoadWrongFile()
+    {
+        $this->assertFalse($this->config->loadFile('wrong_file'));
+    }
+
+    public function testSetCacheChecksum()
+    {
+        $this->config->setCacheChecksum(null);
+        $this->assertNull($this->config->getCacheChecksum());
+        $this->config->setCacheChecksum(false);
+        $this->assertFalse($this->config->getCacheChecksum());
+        $this->config->setCacheChecksum(0);
+        $this->assertFalse($this->config->getCacheChecksum());
+        $this->config->setCacheChecksum('CacheChecksum');
+        $this->assertSame('415a5472d4f94b71ff80fd1c8e9eca7f', $this->config->getCacheChecksum());
+    }
+
+    public function testUpdateCacheChecksum()
+    {
+        $this->config->setCacheChecksum('CacheChecksum');
+        $this->config->updateCacheChecksum(false);
+        $this->assertFalse($this->config->getCacheChecksum());
+
+        $this->config->setCacheChecksum('CacheChecksum');
+        $this->config->updateCacheChecksum(0);
+        $this->assertFalse($this->config->getCacheChecksum());
+
+        $this->config->setCacheChecksum('CacheChecksum');
+        $this->config->updateCacheChecksum('UpdateCacheChecksum');
+        $this->assertSame('894eb161d8e1e48f825d05fdac61afae', $this->config->getCacheChecksum());
+
+        $this->config->setCacheChecksum(false);
+        $this->config->updateCacheChecksum('UpdateCacheChecksum');
+        $this->assertFalse($this->config->getCacheChecksum());
+    }
+
+    public function testValidateCacheChecksum()
+    {
+        $this->config->setCacheChecksum(false);
+        $this->assertFalse($this->config->validateCacheChecksum());
+
+        $this->config->setCacheChecksum(null);
+        $this->assertTrue($this->config->validateCacheChecksum());
+
+        $this->config->setCacheId('cacheId');
+        $this->config->setCacheChecksum('CacheChecksum');
+        $cache = $this->getMock('Magento\Framework\Simplexml\Config\Cache\File', ['load']);
+        $cache->expects($this->once())->method('load')->with('cacheId__CHECKSUM')
+            ->will($this->returnValue('415a5472d4f94b71ff80fd1c8e9eca7f'));
+        $this->config->setCache($cache);
+        $this->assertTrue($this->config->validateCacheChecksum());
+    }
+
+    public function testLoadCache()
+    {
+        $this->config->setCacheChecksum(false);
+        $this->assertFalse($this->config->loadCache());
+
+        $this->config->setCacheId('cacheId');
+        $this->config->setCacheChecksum('CacheChecksum');
+        $cache = $this->getMock('Magento\Framework\Simplexml\Config\Cache\File', ['load']);
+        $this->config->setCache($cache);
+
+        $cache->expects($this->at(0))->method('load')->with('cacheId__CHECKSUM')
+            ->will($this->returnValue('415a5472d4f94b71ff80fd1c8e9eca7f'));
+        $cache->expects($this->at(1))->method('load')->with('cacheId')
+            ->will($this->returnValue(''));
+        $this->config->setCache($cache);
+        $cache->expects($this->at(2))->method('load')->with('cacheId__CHECKSUM')
+            ->will($this->returnValue('415a5472d4f94b71ff80fd1c8e9eca7f'));
+        $cache->expects($this->at(3))->method('load')->with('cacheId')
+            ->will($this->returnValue('<?xml version="1.0"?><config><node>1</node></config>'));
+
+        $this->assertFalse($this->config->loadCache());
+        $this->assertTrue($this->config->loadCache());
+    }
+
+    public function testSaveCache()
+    {
+        $xml = '<config><node>1</node></config>';
+
+        $cache = $this->getMock('Magento\Framework\Simplexml\Config\Cache\File', ['save']);
+        $cache->expects($this->at(0))->method('save')
+            ->with(null, 'cacheId__CHECKSUM', array('cacheTags'), 10)
+            ->will($this->returnValue(true));
+        $cache->expects($this->at(1))->method('save')
+            ->with($xml, 'cacheId', array('cacheTags'), 10)
+            ->will($this->returnValue(true));
+        $cache->expects($this->exactly(2))->method('save');
+
+        $this->config->loadString($xml);
+        $this->config->setCache($cache);
+        $this->config->setCacheChecksum(null);
+        $this->config->setCacheTags(array('cacheTags'));
+        $this->config->setCacheId('cacheId');
+        $this->config->setCacheLifetime(10);
+
+        $this->config->saveCache();
+        $this->config->saveCache();
+        $this->config->setCacheSaved(false);
+        $this->config->setCacheChecksum(false);
+        $this->config->saveCache();
+    }
+
+    public function testRemoveCache()
+    {
+        $cache = $this->getMock('Magento\Framework\Simplexml\Config\Cache\File', ['remove']);
+        $cache->expects($this->at(0))->method('remove')
+            ->with('cacheId')
+            ->will($this->returnValue(true));
+        $cache->expects($this->at(1))->method('remove')
+            ->with('cacheId__CHECKSUM')
+            ->will($this->returnValue(true));
+        $cache->expects($this->exactly(2))->method('remove');
+
+        $this->config->setCache($cache);
+        $this->config->setCacheId('cacheId');
+        $this->config->removeCache();
+    }
+
+    public function testSetNode()
+    {
+        $config = new Config(__DIR__ . '/_files/mixed_data.xml');
+        $config->setNode('node_2', 'new_value');
+        $this->assertSame('new_value', $config->getNode('node_2')->asArray());
+    }
+
+    public function testApplyExtends()
+    {
+        $config = new Config(__DIR__ . '/_files/extend_data.xml');
+        $config->applyExtends();
+        $this->assertEquals(
+            $config->getNode('node_1/node_1_1')->asArray(),
+            $config->getNode('node_3/node_1_1')->asArray()
+        );
+        $config = new Config(__DIR__ . '/_files/data.xml');
+        $config->applyExtends();
+    }
+
+    public function testExtendNode()
+    {
+        $config = new Config(__DIR__ . '/_files/data.xml');
+        $config->extend(new Config('<config><node>1</node></config>'));
+        $this->assertSame('1', $config->getNode('node')->asArray());
     }
-}
+}
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Simplexml/_files/extend_data.xml b/dev/tests/unit/testsuite/Magento/Framework/Simplexml/_files/extend_data.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2043ba099d82e20898239ee25ad5546d00dac6f7
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Simplexml/_files/extend_data.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<root>
+    <node_1 id='1'>
+        Value 1
+        <node_1_1>
+            Value 1.1
+            <node_1_1_1>Value 1.1.1</node_1_1_1>
+        </node_1_1>
+    </node_1>
+    <node_2>
+        <node_2_1>Value 2.1</node_2_1>
+    </node_2>
+    <node_3 extends="node_1"/>
+</root>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Stdlib/DateTime/DateTimeTest.php b/dev/tests/unit/testsuite/Magento/Framework/Stdlib/DateTime/DateTimeTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..fe7d96dcdf2cae92715de2eab05adc753dab6900
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Stdlib/DateTime/DateTimeTest.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\Stdlib\DateTime;
+
+class DateTimeTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Framework\Stdlib\DateTime\DateTime */
+    protected $dateTime;
+
+    /** @var \Magento\Framework\Stdlib\DateTime\Date */
+    protected $date;
+
+    /** @var  \Magento\Framework\Stdlib\DateTime\Timezone|\PHPUnit_Framework_MockObject_MockObject */
+    protected $localeDate;
+
+    protected function setUp()
+    {
+        require_once __DIR__ . '/../_files/gmdate_mock.php';
+        $this->date = new \Magento\Framework\Stdlib\DateTime\Date(1403832149);
+
+        $this->localeDate = $this->getMock(
+            'Magento\Framework\Stdlib\DateTime\Timezone',
+            array('getConfigTimezone', 'date'),
+            array(),
+            '',
+            false
+        );
+        $this->localeDate->expects($this->any())->method('getConfigTimezone')
+            ->will($this->returnValue('America/Los_Angeles'));
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->dateTime = $objectManager->getObject(
+            'Magento\Framework\Stdlib\DateTime\DateTime',
+            array('localeDate' => $this->localeDate)
+        );
+    }
+
+    public function testCalculateOffset()
+    {
+        $this->assertSame(-28800, $this->dateTime->calculateOffset());
+        $this->assertSame(10800, $this->dateTime->calculateOffset('Europe/Kiev'));
+    }
+
+    public function testGmtDate()
+    {
+        $time = 1403858418;
+        $this->localeDate->expects($this->any())->method('date')->with($time)
+            ->will($this->returnValue($this->date));
+        $this->assertSame(false, $this->dateTime->gmtDate(null, 'tro-lo-lo'));
+        $this->assertSame('2014-06-27', $this->dateTime->gmtDate('Y-m-d', $time));
+    }
+
+    public function testDate()
+    {
+        $time = 1403858418;
+        $this->localeDate->expects($this->any())->method('date')->with($time)
+            ->will($this->returnValue($this->date));
+        $this->assertSame('2014-06-26', $this->dateTime->date('Y-m-d', $time));
+        $this->assertSame('2014-06-26 11:22:29', $this->dateTime->date(null, $time));
+    }
+
+    public function testGmtTimestamp()
+    {
+        $time = time();
+        $this->localeDate->expects($this->at(0))->method('date')->with($time)
+            ->will($this->returnValue($this->date));
+        $this->localeDate->expects($this->at(1))->method('date')->with(strtotime("10 September 2000"))
+            ->will($this->returnValue($this->date));
+
+        $this->assertSame(1403857349, $this->dateTime->gmtTimestamp($time));
+        $this->assertSame(1403857349, $this->dateTime->gmtTimestamp("10 September 2000"));
+        $this->assertSame(false, $this->dateTime->gmtTimestamp("la-la-la"));
+        $this->assertSame(1404377188, $this->dateTime->gmtTimestamp());
+    }
+
+    public function testTimestamp()
+    {
+        $time = time();
+        $this->localeDate->expects($this->at(0))->method('date')->with(1404377188)
+            ->will($this->returnValue($this->date));
+        $this->localeDate->expects($this->at(1))->method('date')->with($time)
+            ->will($this->returnValue($this->date));
+        $this->localeDate->expects($this->at(2))->method('date')->with(strtotime("10 September 2000"))
+            ->will($this->returnValue($this->date));
+
+        $this->assertSame(1403806949, $this->dateTime->timestamp());
+        $this->assertSame(1403806949, $this->dateTime->timestamp($time));
+        $this->assertSame(1403806949, $this->dateTime->timestamp("10 September 2000"));
+    }
+
+    public function testGetGmtOffset()
+    {
+        $this->assertSame(-28800, $this->dateTime->getGmtOffset('seconds'));
+        $this->assertSame(-28800, $this->dateTime->getGmtOffset('seconds11'));
+        $this->assertSame(-480, $this->dateTime->getGmtOffset('minutes'));
+        $this->assertSame(-8, $this->dateTime->getGmtOffset('hours'));
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Stdlib/DateTime/TimezoneTest.php b/dev/tests/unit/testsuite/Magento/Framework/Stdlib/DateTime/TimezoneTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3b9e726bb7b21e055282fa3e74a9fe2c68f6561b
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Stdlib/DateTime/TimezoneTest.php
@@ -0,0 +1,195 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\Stdlib\DateTime;
+
+class TimezoneTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Framework\Stdlib\DateTime\Timezone */
+    protected $timezone;
+
+    /** @var \Magento\Backend\Model\Locale\Resolver\Interceptor|\PHPUnit_Framework_MockObject_MockObject */
+    protected $localeResolver;
+
+    /** @var \Magento\Framework\Stdlib\DateTime\DateFactory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $dateFactory;
+
+    /** @var \Magento\Framework\App\Config|\PHPUnit_Framework_MockObject_MockObject */
+    protected $scopeConfig;
+
+    /** @var \Magento\Framework\Locale|\PHPUnit_Framework_MockObject_MockObject */
+    protected $locale;
+
+    /** @var \Magento\Framework\Stdlib\DateTime|\PHPUnit_Framework_MockObject_MockObject */
+    protected $dateTime;
+
+    /** @var \Magento\Store\Model\Resolver\Store|\PHPUnit_Framework_MockObject_MockObject */
+    protected $scopeResolver;
+
+    protected function setUp()
+    {
+        $this->locale = $this->getMock('Magento\Framework\Locale', ['getTranslation', 'toString'], [], '', false);
+        $this->dateTime = $this->getMock('Magento\Framework\Stdlib\DateTime', ['isEmptyDate'], [], '', false);
+        $this->scopeConfig = $this->getMock('Magento\Framework\App\Config', ['getValue'], [], '', false);
+        $this->localeResolver = $this->getMock('Magento\Backend\Model\Locale\Resolver', ['getLocale'], [], '', false);
+        $this->dateFactory = $this->getMock('Magento\Framework\Stdlib\DateTime\DateFactory', ['create'], [], '', false);
+        $this->scopeResolver = $this->getMock('Magento\Store\Model\Resolver\Store', ['getScope'], [], '', false);
+
+        $this->localeResolver->expects($this->any())->method('getLocale')->will($this->returnValue($this->locale));
+        $this->scopeConfig->expects($this->any())->method('getValue')->with('general/locale/timezone', 'store')
+            ->will($this->returnValue('America/Los_Angeles'));
+        $this->locale->expects($this->any())->method('toString')->will($this->returnValue('en_US'));
+
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->timezone = $objectManager->getObject(
+            'Magento\Framework\Stdlib\DateTime\Timezone',
+            [
+                'scopeResolver' => $this->scopeResolver,
+                'localeResolver' => $this->localeResolver,
+                'dateTime' => $this->dateTime,
+                'dateFactory' => $this->dateFactory,
+                'scopeConfig' => $this->scopeConfig,
+                'scopeType' => 'store',
+                'defaultTimezonePath' => 'general/locale/timezone'
+            ]
+        );
+    }
+
+    public function testGetDateFormatWithLongYear()
+    {
+        $this->markTestIncomplete('MAGETWO-26166');
+        $this->locale->staticExpects($this->once())->method('getTranslation')->with('short', 'date')
+            ->will($this->returnValue('M/d/yy'));
+        $this->assertSame('M/d/yyyy', $this->timezone->getDateFormatWithLongYear());
+    }
+
+    public function testDate()
+    {
+        $this->dateFactory->expects($this->any())->method('create')
+            ->with(['date' => null, 'part' => null, 'locale' => $this->locale])
+            ->will($this->returnValue(new \Magento\Framework\Stdlib\DateTime\Date(null, null, $this->locale)));
+        $date = $this->timezone->date();
+        $this->assertSame('America/Los_Angeles', $date->getTimezone());
+    }
+
+    public function testFormatDate()
+    {
+        $time = date('M j, Y');
+        $date1 = new \Magento\Framework\Stdlib\DateTime\Date(1347260400, null, $this->locale);
+        $date2 = new \Magento\Framework\Stdlib\DateTime\Date(strtotime($time), null, $this->locale);
+
+        $this->dateFactory->expects($this->at(0))->method('create')
+            ->will($this->returnValue($date1));
+        $this->dateFactory->expects($this->at(1))->method('create')
+            ->will($this->returnValue($date1));
+        $this->dateFactory->expects($this->at(2))->method('create')
+            ->will($this->returnValue($date2));
+        $this->dateFactory->expects($this->exactly(3))->method('create');
+
+        $this->markTestIncomplete('MAGETWO-26166');
+        $this->locale->staticExpects($this->at(0))->method('getTranslation')
+            ->with('medium', 'date', $this->locale)
+            ->will($this->returnValue('MMM d, y'));
+        $this->locale->staticExpects($this->at(1))->method('getTranslation')
+            ->with('medium', 'time', $this->locale)
+            ->will($this->returnValue('h:mm:ss a'));
+        $this->locale->staticExpects($this->at(2))->method('getTranslation')
+            ->with('medium', 'date', $this->locale)
+            ->will($this->returnValue('MMM d, y'));
+        $this->locale->staticExpects($this->at(3))->method('getTranslation')
+            ->with('medium', 'date', $this->locale)
+            ->will($this->returnValue('MMM d, y'));
+        $this->locale->staticExpects($this->exactly(4))->method('getTranslation');
+
+        $this->assertSame(
+            'Sep 10, 2012 12:00:00 AM',
+            $this->timezone->formatDate("10 September 2012", 'medium', true)
+        );
+        $this->assertSame(
+            'Sep 10, 2012',
+            $this->timezone->formatDate("10 September 2012", 'medium')
+        );
+        $this->assertSame(
+            $time,
+            $this->timezone->formatDate(null, 'medium')
+        );
+        $this->assertSame('date', $this->timezone->formatDate('date', 'wrong'));
+        $this->assertSame('', $this->timezone->formatDate('date'));
+    }
+
+    public function testFormatTime()
+    {
+        $time = date('M j, Y g:m:s A');
+        $date1 = new \Magento\Framework\Stdlib\DateTime\Date(1347260470, null, $this->locale);
+        $date2 = new \Magento\Framework\Stdlib\DateTime\Date(strtotime($time), null, $this->locale);
+
+        $this->dateFactory->expects($this->at(0))->method('create')
+            ->with(['date' => 1347260470, 'part' => null, 'locale' => $this->locale])
+            ->will($this->returnValue($date1));
+        $this->dateFactory->expects($this->at(1))->method('create')->will($this->returnValue($date2));
+        $this->dateFactory->expects($this->exactly(2))->method('create');
+
+        $this->markTestIncomplete('MAGETWO-26166');
+        $this->locale->staticExpects($this->at(0))->method('getTranslation')
+            ->with('medium', 'time', $this->locale)
+            ->will($this->returnValue('h:mm:ss a'));
+        $this->locale->staticExpects($this->at(1))->method('getTranslation')
+            ->with('medium', 'time', $this->locale)
+            ->will($this->returnValue('h:mm:ss a'));
+        $this->locale->staticExpects($this->at(2))->method('getTranslation')
+            ->with('medium', 'date', $this->locale)
+            ->will($this->returnValue('MMM d, y'));
+        $this->locale->staticExpects($this->at(3))->method('getTranslation')
+            ->with('medium', 'time', $this->locale)
+            ->will($this->returnValue('h:mm:ss a'));
+        $this->locale->staticExpects($this->exactly(4))->method('getTranslation');
+
+        $this->assertSame('10 September 2012', $this->timezone->formatTime('10 September 2012', 'wrong_type'));
+        $this->assertSame('12:01:10 AM', $this->timezone->formatTime('September 10, 2012 12:01:10 AM', 'medium'));
+        $this->assertSame('12:01:10 AM', $this->timezone->formatTime($date1, 'medium'));
+        $this->assertSame($time, $this->timezone->formatTime(null, 'medium', true));
+    }
+
+    public function testUtcDate()
+    {
+        $this->dateFactory->expects($this->any())->method('create')
+            ->with(['date' => 1347260470, 'part' => null, 'locale' => $this->locale])
+            ->will($this->returnValue(new \Magento\Framework\Stdlib\DateTime\Date(1347260470, null, $this->locale)));
+
+        $date = $this->timezone->utcDate('general/locale/timezone', 1347260470);
+        $this->assertSame('UTC', $date->getTimezone());
+    }
+
+    public function testIsScopeDateInInterval()
+    {
+        $scope = $this->getMock('Magento\Framework\App\ScopeInterface', ['getCode', 'getId']);
+        $this->scopeResolver->expects($this->any())->method('getScope')->will($this->returnValue($scope));
+        $this->dateTime->expects($this->at(0))->method('isEmptyDate')->will($this->returnValue(false));
+        $this->dateTime->expects($this->at(1))->method('isEmptyDate')->will($this->returnValue(false));
+        $this->dateTime->expects($this->at(2))->method('isEmptyDate')->will($this->returnValue(true));
+        $this->dateTime->expects($this->at(3))->method('isEmptyDate')->will($this->returnValue(true));
+
+        $this->assertFalse($this->timezone->isScopeDateInInterval('store'));
+        $this->assertTrue($this->timezone->isScopeDateInInterval('store', null, '10 September 2036'));
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Stdlib/StringTest.php b/dev/tests/unit/testsuite/Magento/Framework/Stdlib/StringTest.php
index 723d1514f96333bb804da91951ba9b3b1b5395dd..d584c6f8f74a82032c4c3f514ed15cc3ed962886 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Stdlib/StringTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Stdlib/StringTest.php
@@ -50,6 +50,10 @@ class StringTest extends \PHPUnit_Framework_TestCase
             array('12345', '123', '12345', '6789'),
             $this->_string->split('12345  123    123456789', 5, true, true)
         );
+        $this->assertEquals(
+            array('1234', '5', '123', '1234', '5678', '9'),
+            $this->_string->split('12345  123    123456789', 4, true, true)
+        );
     }
 
     /**
@@ -70,6 +74,17 @@ class StringTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals($string, $this->_string->cleanString($string));
     }
 
+    public function testSubstr()
+    {
+        $this->assertSame('tring', $this->_string->substr('string', 1));
+    }
+
+    public function testStrrev()
+    {
+        $this->assertSame('0987654321', $this->_string->strrev('1234567890'));
+        $this->assertSame('', $this->_string->strrev(''));
+    }
+
     /**
      * @covers \Magento\Framework\Stdlib\String::strpos
      */
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Stdlib/_files/gmdate_mock.php b/dev/tests/unit/testsuite/Magento/Framework/Stdlib/_files/gmdate_mock.php
new file mode 100644
index 0000000000000000000000000000000000000000..627e244e5b2fb6c2115994429ca3fda7cc804dd4
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Stdlib/_files/gmdate_mock.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\Stdlib\DateTime;
+
+/**
+ * Override standard function
+ */
+function gmdate()
+{
+    return 1404377188;
+}
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Framework/TranslateTest.php b/dev/tests/unit/testsuite/Magento/Framework/TranslateTest.php
index 2301ef7bb2ce322abde52d7ed8fabbdc4d32eca8..9c6296ef00dacff4cc08d1240009b77e5c1c3096 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/TranslateTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/TranslateTest.php
@@ -23,90 +23,88 @@
  */
 namespace Magento\Framework;
 
-use Magento\TestFramework\Matcher\MethodInvokedAtIndex;
-
 /**
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
 class TranslateTest extends \PHPUnit_Framework_TestCase
 {
     /** @var Translate */
-    protected $_translate;
+    protected $translate;
 
-    /** @var \Magento\Framework\View\DesignInterface */
-    protected $_viewDesign;
+    /** @var \Magento\Framework\View\DesignInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $viewDesign;
 
-    /** @var \Magento\Framework\Cache\FrontendInterface */
-    protected $_cache;
+    /** @var \Magento\Framework\Cache\FrontendInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $cache;
 
-    /** @var \Magento\Framework\View\FileSystem */
-    protected $_viewFileSystem;
+    /** @var \Magento\Framework\View\FileSystem|\PHPUnit_Framework_MockObject_MockObject */
+    protected $viewFileSystem;
 
-    /** @var \Magento\Framework\Module\ModuleList */
-    protected $_moduleList;
+    /** @var \Magento\Framework\Module\ModuleList|\PHPUnit_Framework_MockObject_MockObject */
+    protected $moduleList;
 
-    /** @var \Magento\Framework\Module\Dir\Reader */
-    protected $_modulesReader;
+    /** @var \Magento\Framework\Module\Dir\Reader|\PHPUnit_Framework_MockObject_MockObject */
+    protected $modulesReader;
 
-    /** @var \Magento\Framework\App\ScopeResolverInterface */
-    protected $_scopeResolver;
+    /** @var \Magento\Framework\App\ScopeResolverInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $scopeResolver;
 
-    /** @var \Magento\Framework\Translate\ResourceInterface */
-    protected $_resource;
+    /** @var \Magento\Framework\Translate\ResourceInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $resource;
 
-    /** @var \Magento\Framework\Locale\ResolverInterface */
-    protected $_locale;
+    /** @var \Magento\Framework\Locale\ResolverInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $locale;
 
-    /** @var \Magento\Framework\App\State */
-    protected $_appState;
+    /** @var \Magento\Framework\App\State|\PHPUnit_Framework_MockObject_MockObject */
+    protected $appState;
 
-    /** @var \Magento\Framework\App\Filesystem */
-    protected $_filesystem;
+    /** @var \Magento\Framework\App\Filesystem|\PHPUnit_Framework_MockObject_MockObject */
+    protected $filesystem;
 
-    /** @var \Magento\Framework\App\RequestInterface */
-    protected $_request;
+    /** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $request;
 
-    /** @var \Magento\Framework\File\Csv */
-    protected $_csvParser;
+    /** @var \Magento\Framework\File\Csv|\PHPUnit_Framework_MockObject_MockObject */
+    protected $csvParser;
 
     /** @var  \Magento\Framework\App\Language\Dictionary|\PHPUnit_Framework_MockObject_MockObject */
-    protected $_packDictionary;
+    protected $packDictionary;
 
-    /** @var \Magento\Framework\Filesystem\Directory\ReadInterface */
-    protected $_directory;
+    /** @var \Magento\Framework\Filesystem\Directory\ReadInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $directory;
 
     public function setUp()
     {
-        $this->_viewDesign = $this->getMock('\Magento\Framework\View\DesignInterface', [], [], '', false);
-        $this->_cache = $this->getMock('\Magento\Framework\Cache\FrontendInterface', [], [], '', false);
-        $this->_viewFileSystem = $this->getMock('\Magento\Framework\View\FileSystem', [], [], '', false);
-        $this->_moduleList = $this->getMock('\Magento\Framework\Module\ModuleList', [], [], '', false);
-        $this->_modulesReader = $this->getMock('\Magento\Framework\Module\Dir\Reader', [], [], '', false);
-        $this->_scopeResolver = $this->getMock('\Magento\Framework\App\ScopeResolverInterface', [], [], '', false);
-        $this->_resource = $this->getMock('\Magento\Framework\Translate\ResourceInterface', [], [], '', false);
-        $this->_locale = $this->getMock('\Magento\Framework\Locale\ResolverInterface', [], [], '', false);
-        $this->_appState = $this->getMock('\Magento\Framework\App\State', [], [], '', false);
-        $this->_request = $this->getMock('\Magento\Framework\App\RequestInterface', [], [], '', false);
-        $this->_csvParser = $this->getMock('\Magento\Framework\File\Csv', [], [], '', false);
-        $this->_packDictionary = $this->getMock('\Magento\Framework\App\Language\Dictionary', [], [], '', false);
-        $this->_directory = $this->getMock('\Magento\Framework\Filesystem\Directory\ReadInterface', [], [], '', false);
+        $this->viewDesign = $this->getMock('\Magento\Framework\View\DesignInterface', [], [], '', false);
+        $this->cache = $this->getMock('\Magento\Framework\Cache\FrontendInterface', [], [], '', false);
+        $this->viewFileSystem = $this->getMock('\Magento\Framework\View\FileSystem', [], [], '', false);
+        $this->moduleList = $this->getMock('\Magento\Framework\Module\ModuleList', [], [], '', false);
+        $this->modulesReader = $this->getMock('\Magento\Framework\Module\Dir\Reader', [], [], '', false);
+        $this->scopeResolver = $this->getMock('\Magento\Framework\App\ScopeResolverInterface', [], [], '', false);
+        $this->resource = $this->getMock('\Magento\Framework\Translate\ResourceInterface', [], [], '', false);
+        $this->locale = $this->getMock('\Magento\Framework\Locale\ResolverInterface', [], [], '', false);
+        $this->appState = $this->getMock('\Magento\Framework\App\State', [], [], '', false);
+        $this->request = $this->getMock('\Magento\Framework\App\RequestInterface', [], [], '', false);
+        $this->csvParser = $this->getMock('\Magento\Framework\File\Csv', [], [], '', false);
+        $this->packDictionary = $this->getMock('\Magento\Framework\App\Language\Dictionary', [], [], '', false);
+        $this->directory = $this->getMock('\Magento\Framework\Filesystem\Directory\ReadInterface', [], [], '', false);
         $filesystem = $this->getMock('\Magento\Framework\App\Filesystem', [], [], '', false);
-        $filesystem->expects($this->once())->method('getDirectoryRead')->will($this->returnValue($this->_directory));
-
-        $this->_translate = new Translate(
-            $this->_viewDesign,
-            $this->_cache,
-            $this->_viewFileSystem,
-            $this->_moduleList,
-            $this->_modulesReader,
-            $this->_scopeResolver,
-            $this->_resource,
-            $this->_locale,
-            $this->_appState,
+        $filesystem->expects($this->once())->method('getDirectoryRead')->will($this->returnValue($this->directory));
+
+        $this->translate = new Translate(
+            $this->viewDesign,
+            $this->cache,
+            $this->viewFileSystem,
+            $this->moduleList,
+            $this->modulesReader,
+            $this->scopeResolver,
+            $this->resource,
+            $this->locale,
+            $this->appState,
             $filesystem,
-            $this->_request,
-            $this->_csvParser,
-            $this->_packDictionary
+            $this->request,
+            $this->csvParser,
+            $this->packDictionary
         );
     }
 
@@ -119,30 +117,37 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
      */
     public function testLoadData($area, $forceReload, $cachedData)
     {
-        $this->_expectsSetConfig('themeId');
+        $this->expectsSetConfig('themeId');
 
-        $this->_cache->expects($this->exactly($forceReload ? 0 : 1))
+        $this->cache->expects($this->exactly($forceReload ? 0 : 1))
             ->method('load')
             ->will($this->returnValue(serialize($cachedData)));
 
         if (!$forceReload && $cachedData !== false) {
-            $this->_translate->loadData($area, $forceReload);
-            $this->assertEquals($cachedData, $this->_translate->getData());
+            $this->translate->loadData($area, $forceReload);
+            $this->assertEquals($cachedData, $this->translate->getData());
             return;
         }
 
-        $this->_directory->expects($this->any())->method('isExist')->will($this->returnValue(true));
+        $this->directory->expects($this->any())->method('isExist')->will($this->returnValue(true));
 
         // _loadModuleTranslation()
         $modules = [['name' => 'module']];
-        $this->_moduleList->expects($this->once())->method('getModules')->will($this->returnValue($modules));
+        $this->moduleList->expects($this->once())->method('getModules')->will($this->returnValue($modules));
         $moduleData = [
             'module original' => 'module translated',
-            'module original2' => 'module original2'
+            'module theme' => 'module-theme original translated',
+            'module pack' => 'module-pack original translated',
+            'module db' => 'module-db original translated',
+        ];
+        $this->modulesReader->expects($this->any())->method('getModuleDir')->will($this->returnValue('/app/module'));
+        $themeData = [
+            'theme original' => 'theme translated',
+            'module theme' => 'theme translated overwrite',
+            'module pack' => 'theme-pack translated overwrite',
+            'module db' => 'theme-db translated overwrite',
         ];
-        $this->_modulesReader->expects($this->any())->method('getModuleDir')->will($this->returnValue('/app/module'));
-        $themeData = ['theme original' => 'theme translated'];
-        $this->_csvParser->expects($this->any())
+        $this->csvParser->expects($this->any())
             ->method('getDataPairs')
             ->will(
                 $this->returnValueMap(
@@ -155,30 +160,40 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
             );
 
         // _loadThemeTranslation()
-        $this->_viewFileSystem->expects($this->any())
+        $this->viewFileSystem->expects($this->any())
             ->method('getLocaleFileName')
             ->will($this->returnValue('/theme.csv'));
 
         // _loadPackTranslation
-        $packData = ['pack original' => 'pack translated'];
-        $this->_packDictionary->expects($this->once())->method('getDictionary')->will($this->returnValue($packData));
+        $packData = [
+            'pack original' => 'pack translated',
+            'module pack' => 'pack translated overwrite',
+            'module db' => 'pack-db translated overwrite',
+        ];
+        $this->packDictionary->expects($this->once())->method('getDictionary')->will($this->returnValue($packData));
 
         // _loadDbTranslation()
-        $dbData = ['db original' => 'db translated'];
-        $this->_resource->expects($this->any())->method('getTranslationArray')->will($this->returnValue($dbData));
+        $dbData = [
+            'db original' => 'db translated',
+            'module db' => 'db translated overwrite',
+        ];
+        $this->resource->expects($this->any())->method('getTranslationArray')->will($this->returnValue($dbData));
 
-        $this->_cache->expects($this->exactly($forceReload ? 0 : 1))
+        $this->cache->expects($this->exactly($forceReload ? 0 : 1))
             ->method('save');
 
-        $this->_translate->loadData($area, $forceReload);
+        $this->translate->loadData($area, $forceReload);
 
         $expected = [
             'module original' => 'module translated',
+            'module theme' => 'theme translated overwrite',
+            'module pack' => 'pack translated overwrite',
+            'module db' => 'db translated overwrite',
             'theme original' => 'theme translated',
             'pack original' => 'pack translated',
-            'db original' => 'db translated'
+            'db original' => 'db translated',
         ];
-        $this->assertEquals($expected, $this->_translate->getData());
+        $this->assertEquals($expected, $this->translate->getData());
     }
 
     public function dataProviderForTestLoadData()
@@ -186,12 +201,17 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
         $cachedData = ['cached 1' => 'translated 1', 'cached 2' => 'translated 2'];
         return [
             ['adminhtml', true, false],
+            ['adminhtml', true, $cachedData],
             ['adminhtml', false, $cachedData],
+            ['adminhtml', false, false],
             ['frontend', true, false],
+            ['frontend', true, $cachedData],
             ['frontend', false, $cachedData],
+            ['frontend', false, false],
             [null, true, false],
+            [null, true, $cachedData],
             [null, false, $cachedData],
-            ['adminhtml', false, false]
+            [null, false, false]
         ];
     }
 
@@ -202,12 +222,12 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
      */
     public function testGetData($data, $result)
     {
-        $this->_cache->expects($this->once())
+        $this->cache->expects($this->once())
             ->method('load')
             ->will($this->returnValue(serialize($data)));
-        $this->_expectsSetConfig('themeId');
-        $this->_translate->loadData('frontend');
-        $this->assertEquals($result, $this->_translate->getData());
+        $this->expectsSetConfig('themeId');
+        $this->translate->loadData('frontend');
+        $this->assertEquals($result, $this->translate->getData());
     }
 
     public function dataProviderForTestGetData()
@@ -221,56 +241,56 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
 
     public function testGetLocale()
     {
-        $this->_locale->expects($this->once())->method('getLocaleCode')->will($this->returnValue('en_US'));
-        $this->assertEquals('en_US', $this->_translate->getLocale());
+        $this->locale->expects($this->once())->method('getLocaleCode')->will($this->returnValue('en_US'));
+        $this->assertEquals('en_US', $this->translate->getLocale());
 
-        $this->_locale->expects($this->never())->method('getLocaleCode');
-        $this->assertEquals('en_US', $this->_translate->getLocale());
+        $this->locale->expects($this->never())->method('getLocaleCode');
+        $this->assertEquals('en_US', $this->translate->getLocale());
 
-        $this->_locale->expects($this->never())->method('getLocaleCode');
-        $this->_translate->setLocale('en_GB');
-        $this->assertEquals('en_GB', $this->_translate->getLocale());
+        $this->locale->expects($this->never())->method('getLocaleCode');
+        $this->translate->setLocale('en_GB');
+        $this->assertEquals('en_GB', $this->translate->getLocale());
     }
 
     public function testSetLocale()
     {
-        $this->_translate->setLocale('en_GB');
-        $this->_locale->expects($this->never())->method('getLocaleCode');
-        $this->assertEquals('en_GB', $this->_translate->getLocale());
+        $this->translate->setLocale('en_GB');
+        $this->locale->expects($this->never())->method('getLocaleCode');
+        $this->assertEquals('en_GB', $this->translate->getLocale());
     }
 
     public function testGetTheme()
     {
-        $this->_request->expects($this->at(0))->method('getParam')->with('theme')->will($this->returnValue(''));
+        $this->request->expects($this->at(0))->method('getParam')->with('theme')->will($this->returnValue(''));
 
         $requestTheme = array('theme_title' => 'Theme Title');
-        $this->_request->expects($this->at(1))->method('getParam')->with('theme')
+        $this->request->expects($this->at(1))->method('getParam')->with('theme')
             ->will($this->returnValue($requestTheme));
 
-        $this->assertEquals('theme', $this->_translate->getTheme());
-        $this->assertEquals('themeTheme Title', $this->_translate->getTheme());
+        $this->assertEquals('theme', $this->translate->getTheme());
+        $this->assertEquals('themeTheme Title', $this->translate->getTheme());
     }
 
     public function testLoadDataNoTheme()
     {
         $forceReload = true;
-        $this->_expectsSetConfig(null, null);
-        $this->_moduleList->expects($this->once())->method('getModules')->will($this->returnValue([]));
-        $this->_appState->expects($this->once())->method('getAreaCode')->will($this->returnValue('frontend'));
-        $this->_packDictionary->expects($this->once())->method('getDictionary')->will($this->returnValue([]));
-        $this->_resource->expects($this->any())->method('getTranslationArray')->will($this->returnValue([]));
-        $this->assertEquals($this->_translate, $this->_translate->loadData(null, $forceReload));
+        $this->expectsSetConfig(null, null);
+        $this->moduleList->expects($this->once())->method('getModules')->will($this->returnValue([]));
+        $this->appState->expects($this->once())->method('getAreaCode')->will($this->returnValue('frontend'));
+        $this->packDictionary->expects($this->once())->method('getDictionary')->will($this->returnValue([]));
+        $this->resource->expects($this->any())->method('getTranslationArray')->will($this->returnValue([]));
+        $this->assertEquals($this->translate, $this->translate->loadData(null, $forceReload));
     }
 
     /**
      * Declare calls expectation for setConfig() method
      */
-    protected function _expectsSetConfig($themeId, $localeCode = 'en_US')
+    protected function expectsSetConfig($themeId, $localeCode = 'en_US')
     {
-        $this->_locale->expects($this->any())->method('getLocaleCode')->will($this->returnValue($localeCode));
-        $scope = new \Magento\Framework\Object();
-        $scopeAdmin = new \Magento\Framework\Object(['code' => 'adminCode', 'id' => 1]);
-        $this->_scopeResolver->expects($this->any())
+        $this->locale->expects($this->any())->method('getLocaleCode')->will($this->returnValue($localeCode));
+        $scope = new \Magento\Framework\Object(['code' => 'frontendCode', 'id' => 1]);
+        $scopeAdmin = new \Magento\Framework\Object(['code' => 'adminCode', 'id' => 0]);
+        $this->scopeResolver->expects($this->any())
             ->method('getScope')
             ->will(
                 $this->returnValueMap(
@@ -281,6 +301,6 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
                 )
             );
         $designTheme = new \Magento\Framework\Object(['id' => $themeId]);
-        $this->_viewDesign->expects($this->any())->method('getDesignTheme')->will($this->returnValue($designTheme));
+        $this->viewDesign->expects($this->any())->method('getDesignTheme')->will($this->returnValue($designTheme));
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/BlockPoolTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/BlockPoolTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1bddc2cd7a028a0d3a3c9039ab8441ad4edf0830
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/BlockPoolTest.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\View;
+
+/**
+ * Test for view BlockPool model
+ */
+class BlockPoolTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var BlockPool
+     */
+    protected $blockPool;
+
+    /**
+     * Block factory
+     * @var \Magento\Framework\View\Element\BlockFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $blockFactory;
+
+    protected function setUp()
+    {
+        $this->blockFactory = $this->getMockBuilder('Magento\Framework\View\Element\BlockFactory')
+            ->disableOriginalConstructor()
+            ->setMethods(['createBlock'])
+            ->getMock();
+        $this->blockPool = new BlockPool($this->blockFactory);
+    }
+
+    public function testAdd()
+    {
+        $blockName = 'testName';
+        $blockClass = '\Magento\Framework\View\BlockPoolTestBlock';
+        $arguments = ['key' => 'value'];
+
+        $block = $this->getMock('Magento\Framework\View\BlockPoolTestBlock');
+
+        $this->blockFactory->expects($this->atLeastOnce())
+            ->method('createBlock')
+            ->with($blockClass, $arguments)
+            ->will($this->returnValue($block));
+
+        $this->assertEquals($this->blockPool, $this->blockPool->add($blockName, $blockClass, $arguments));
+
+        $this->assertEquals([$blockName => $block], $this->blockPool->get());
+        $this->assertEquals($block, $this->blockPool->get($blockName));
+        $this->assertNull($this->blockPool->get('someWrongName'));
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage Invalid Block class name: NotExistingBlockClass
+     */
+    public function testAddWithException()
+    {
+        $this->blockPool->add('BlockPoolTestBlock', 'NotExistingBlockClass');
+    }
+}
+
+/**
+ * Class BlockPoolTestBlock mock
+ */
+class BlockPoolTestBlock implements \Magento\Framework\View\Element\BlockInterface
+{
+    /**
+     * Produce and return block's html output
+     *
+     * @return string
+     */
+    public function toHtml()
+    {
+        return '';
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/ConfigTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..81ec3b6d814bcb9e668cdb45e3d08c47536e145e
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/ConfigTest.php
@@ -0,0 +1,134 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\View;
+
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+
+class ConfigTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Framework\View\Config */
+    protected $config;
+
+    /** @var ObjectManagerHelper */
+    protected $objectManagerHelper;
+
+    /** @var \Magento\Framework\Module\Dir\Reader|\PHPUnit_Framework_MockObject_MockObject */
+    protected $readerMock;
+
+    /** @var \Magento\Framework\App\Filesystem|\PHPUnit_Framework_MockObject_MockObject */
+    protected $filesystemMock;
+
+    /** @var \Magento\Framework\View\Asset\Repository|\PHPUnit_Framework_MockObject_MockObject */
+    protected $repositoryMock;
+
+    /** @var \Magento\Framework\View\FileSystem|\PHPUnit_Framework_MockObject_MockObject */
+    protected $fileSystemMock;
+
+    /** @var \Magento\Framework\Config\FileIteratorFactory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $fileIteratorFactoryMock;
+
+    /** @var \Magento\Framework\Filesystem\Directory\ReadInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $directoryReadMock;
+
+    protected function setUp()
+    {
+        $this->readerMock = $this->getMock('Magento\Framework\Module\Dir\Reader', [], [], '', false);
+        $this->filesystemMock = $this->getMock('Magento\Framework\App\Filesystem', [], [], '', false);
+        $this->directoryReadMock = $this->getMock('Magento\Framework\Filesystem\Directory\ReadInterface');
+        $this->filesystemMock->expects($this->once())
+            ->method('getDirectoryRead')
+            ->with($this->equalTo(\Magento\Framework\App\Filesystem::ROOT_DIR))
+            ->will($this->returnValue($this->directoryReadMock));
+        $this->repositoryMock = $this->getMock('Magento\Framework\View\Asset\Repository', [], [], '', false);
+        $this->fileSystemMock = $this->getMock('Magento\Framework\View\FileSystem', [], [], '', false);
+        $this->fileIteratorFactoryMock = $this->getMock('Magento\Framework\Config\FileIteratorFactory');
+
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->config = $this->objectManagerHelper->getObject(
+            'Magento\Framework\View\Config',
+            [
+                'moduleReader' => $this->readerMock,
+                'filesystem' => $this->filesystemMock,
+                'assetRepo' => $this->repositoryMock,
+                'viewFileSystem' => $this->fileSystemMock,
+                'fileIteratorFactory' => $this->fileIteratorFactoryMock
+            ]
+        );
+    }
+
+    public function testGetViewConfig()
+    {
+        $themeMock = $this->getMock(
+            'Magento\Core\Model\Theme',
+            ['getId', 'getCustomization', 'getCustomViewConfigPath'],
+            [],
+            '',
+            false
+        );
+        $themeMock->expects($this->atLeastOnce())
+            ->method('getId')
+            ->will($this->returnValue(2));
+        $themeMock->expects($this->once())
+            ->method('getCustomization')
+            ->will($this->returnSelf());
+        $themeMock->expects($this->once())
+            ->method('getCustomViewConfigPath')
+            ->will($this->returnValue(''));
+        $params = ['themeModel' => $themeMock];
+        $configFile = 'config.xml';
+        $this->repositoryMock->expects($this->atLeastOnce())
+            ->method('updateDesignParams')
+            ->with($this->equalTo($params))
+            ->will($this->returnSelf());
+        $iterator = $this->getMock('Magento\Framework\Config\FileIterator', [], [], '', false);
+        $iterator->expects($this->once())
+            ->method('toArray')
+            ->will($this->returnValue([]));
+        $this->readerMock->expects($this->once())
+            ->method('getConfigurationFiles')
+            ->with($this->equalTo(basename(\Magento\Framework\View\ConfigInterface::CONFIG_FILE_NAME)))
+            ->will($this->returnValue($iterator));
+        $this->directoryReadMock->expects($this->once())
+            ->method('isExist')
+            ->with($this->anything())
+            ->will($this->returnValue(true));
+        $this->fileSystemMock->expects($this->once())
+            ->method('getFilename')
+            ->with($this->equalTo(\Magento\Framework\View\ConfigInterface::CONFIG_FILE_NAME), $params)
+            ->will($this->returnValue($configFile));
+        $this->directoryReadMock->expects($this->any())
+            ->method('getRelativePath')
+            ->with($this->equalTo($configFile))
+            ->will($this->returnArgument(0));
+        $xmlData = '<view><vars module="Magento_Catalog"><var name="test">1</var></vars></view>';
+        $this->directoryReadMock->expects($this->once())
+            ->method('readFile')
+            ->with($this->equalTo($configFile))
+            ->will($this->returnValue($xmlData));
+        $this->assertInstanceOf('Magento\Framework\Config\View', $this->config->getViewConfig($params));
+        // lazy load test
+        $this->assertInstanceOf('Magento\Framework\Config\View', $this->config->getViewConfig($params));
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/ContextTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/ContextTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b67be10a2b3ad6be29a658405dc9d789197e19d9
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/ContextTest.php
@@ -0,0 +1,330 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/**
+ * Test for view Context model
+ */
+namespace Magento\Framework\View;
+
+class ContextTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Context
+     */
+    protected $context;
+
+    /**
+     * @var \Magento\Framework\App\State|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $appState;
+
+    /**
+     * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $request;
+
+    /**
+     * @var \Magento\Framework\View\DesignInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $design;
+
+    protected function setUp()
+    {
+        $this->appState = $this->getMockBuilder('Magento\Framework\App\State')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->request = $this->getMockBuilder('Magento\Framework\App\Request\Http')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->design = $this->getMockBuilder('Magento\Framework\View\DesignInterface')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->context = $objectManager->getObject('Magento\Framework\View\Context', array(
+            'appState' => $this->appState,
+            'request' => $this->request,
+            'design' => $this->design
+        ));
+    }
+
+    public function testGetCache()
+    {
+        $this->assertInstanceOf('\Magento\Framework\App\CacheInterface', $this->context->getCache());
+    }
+
+    public function testGetDesignPackage()
+    {
+        $this->assertInstanceOf('\Magento\Framework\View\DesignInterface', $this->context->getDesignPackage());
+    }
+
+    public function testGetEventManager()
+    {
+        $this->assertInstanceOf('\Magento\Framework\Event\ManagerInterface', $this->context->getEventManager());
+    }
+
+    public function testGetFrontController()
+    {
+        $this->assertInstanceOf(
+            '\Magento\Framework\App\FrontControllerInterface',
+            $this->context->getFrontController()
+        );
+    }
+
+    public function testGetLayout()
+    {
+        $this->assertInstanceOf('\Magento\Framework\View\LayoutInterface', $this->context->getLayout());
+    }
+
+    public function testGetRequest()
+    {
+        $this->assertInstanceOf('\Magento\Framework\App\Request\Http', $this->context->getRequest());
+    }
+
+    public function testGetSession()
+    {
+        $this->assertInstanceOf('\Magento\Framework\Session\SessionManagerInterface', $this->context->getSession());
+    }
+
+    public function testGetScopeConfig()
+    {
+        $this->assertInstanceOf('\Magento\Framework\App\Config\ScopeConfigInterface', $this->context->getScopeConfig());
+    }
+
+    public function testGetTranslator()
+    {
+        $this->assertInstanceOf('\Magento\Framework\TranslateInterface', $this->context->getTranslator());
+    }
+
+    public function testGetUrlBuilder()
+    {
+        $this->assertInstanceOf('\Magento\Framework\UrlInterface', $this->context->getUrlBuilder());
+    }
+
+    public function testGetViewConfig()
+    {
+        $this->assertInstanceOf('\Magento\Framework\View\ConfigInterface', $this->context->getViewConfig());
+    }
+
+    public function testGetCacheState()
+    {
+        $this->assertInstanceOf('\Magento\Framework\App\Cache\StateInterface', $this->context->getCacheState());
+    }
+
+    public function testGetLogger()
+    {
+        $this->assertInstanceOf('\Magento\Framework\Logger', $this->context->getLogger());
+    }
+
+    public function testGetAppState()
+    {
+        $this->assertInstanceOf('\Magento\Framework\App\State', $this->context->getAppState());
+    }
+
+    public function testGetArea()
+    {
+        $area = 'frontendArea';
+
+        $this->appState->expects($this->once())
+            ->method('getAreaCode')
+            ->will($this->returnValue($area));
+
+        $this->assertEquals($area, $this->context->getArea());
+    }
+
+    public function testGetModuleName()
+    {
+        $moduleName = 'testModuleName';
+
+        $this->request->expects($this->once())
+            ->method('getModuleName')
+            ->will($this->returnValue($moduleName));
+
+        $this->assertEquals($moduleName, $this->context->getModuleName());
+    }
+
+    public function testGetFrontName()
+    {
+        $frontName = 'testFrontName';
+
+        $this->request->expects($this->once())
+            ->method('getModuleName')
+            ->will($this->returnValue($frontName));
+
+        $this->assertEquals($frontName, $this->context->getFrontName());
+    }
+
+    public function testGetControllerName()
+    {
+        $controllerName = 'testControllerName';
+
+        $this->request->expects($this->once())
+            ->method('getControllerName')
+            ->will($this->returnValue($controllerName));
+
+        $this->assertEquals($controllerName, $this->context->getControllerName());
+    }
+
+    public function testGetActionName()
+    {
+        $actionName = 'testActionName';
+
+        $this->request->expects($this->once())
+            ->method('getActionName')
+            ->will($this->returnValue($actionName));
+
+        $this->assertEquals($actionName, $this->context->getActionName());
+    }
+
+    public function testGetFullActionName()
+    {
+        $frontName = 'testFrontName';
+        $controllerName = 'testControllerName';
+        $actionName = 'testActionName';
+        $fullActionName = 'testfrontname_testcontrollername_testactionname';
+
+        $this->request->expects($this->once())
+            ->method('getModuleName')
+            ->will($this->returnValue($frontName));
+
+        $this->request->expects($this->once())
+            ->method('getControllerName')
+            ->will($this->returnValue($controllerName));
+
+        $this->request->expects($this->once())
+            ->method('getActionName')
+            ->will($this->returnValue($actionName));
+
+        $this->assertEquals($fullActionName, $this->context->getFullActionName());
+    }
+
+    /**
+     * @param string $headerAccept
+     * @param string $acceptType
+     *
+     * @dataProvider getAcceptTypeDataProvider
+     */
+    public function testGetAcceptType($headerAccept, $acceptType)
+    {
+        $this->request->expects($this->once())
+            ->method('getHeader')
+            ->with('Accept')
+            ->will($this->returnValue($headerAccept));
+
+        $this->assertEquals($acceptType, $this->context->getAcceptType());
+    }
+
+    public function getAcceptTypeDataProvider()
+    {
+        return [
+            ['json', 'json'],
+            ['testjson', 'json'],
+            ['soap', 'soap'],
+            ['testsoap', 'soap'],
+            ['text/html', 'html'],
+            ['testtext/html', 'html'],
+            ['xml', 'xml'],
+            ['someElse', 'xml'],
+        ];
+    }
+
+    public function testGetPost()
+    {
+        $key = 'getParamName';
+        $default = 'defaultGetParamValue';
+        $postValue = 'someGetParamValue';
+
+        $this->request->expects($this->once())
+            ->method('getPost')
+            ->with($key, $default)
+            ->will($this->returnValue($postValue));
+
+        $this->assertEquals($postValue, $this->context->getPost($key, $default));
+    }
+
+    public function testGetQuery()
+    {
+        $key = 'getParamName';
+        $default = 'defaultGetParamValue';
+        $queryValue = 'someGetParamValue';
+
+        $this->request->expects($this->once())
+            ->method('getPost')
+            ->with($key, $default)
+            ->will($this->returnValue($queryValue));
+
+        $this->assertEquals($queryValue, $this->context->getQuery($key, $default));
+    }
+
+    public function testGetParam()
+    {
+        $key = 'paramName';
+        $default = 'defaultParamValue';
+        $paramValue = 'someParamValue';
+
+        $this->request->expects($this->once())
+            ->method('getParam')
+            ->with($key, $default)
+            ->will($this->returnValue($paramValue));
+
+        $this->assertEquals($paramValue, $this->context->getParam($key, $default));
+    }
+
+    public function testGetParams()
+    {
+        $params = ['paramName' => 'value'];
+
+        $this->request->expects($this->once())
+            ->method('getParams')
+            ->will($this->returnValue($params));
+
+        $this->assertEquals($params, $this->context->getParams());
+    }
+
+    public function testGetHeader()
+    {
+        $headerName = 'headerName';
+        $headerValue = 'headerValue';
+
+        $this->request->expects($this->once())
+            ->method('getHeader')
+            ->with($headerName)
+            ->will($this->returnValue($headerValue));
+
+        $this->assertEquals($headerValue, $this->context->getHeader($headerName));
+    }
+
+    public function testGetRawBody()
+    {
+        $rawBody = 'body string';
+
+        $this->request->expects($this->once())
+            ->method('getRawBody')
+            ->will($this->returnValue($rawBody));
+
+        $this->assertEquals($rawBody, $this->context->getRawBody());
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/DataSourcePoolTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/DataSourcePoolTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..369314fec23f3c925c3255b182b02f39bce3f6f4
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/DataSourcePoolTest.php
@@ -0,0 +1,133 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\View;
+
+/**
+ * Test for view Context model
+ */
+class DataSourcePoolTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var DataSourcePool
+     */
+    protected $dataSourcePool;
+
+    /**
+     * @var \Magento\Framework\View\Element\BlockFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $blockFactory;
+
+    protected function setUp()
+    {
+        $this->blockFactory = $this->getMockBuilder('Magento\Framework\View\Element\BlockFactory')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->dataSourcePool = $objectManager->getObject('Magento\Framework\View\DataSourcePool', [
+            'blockFactory' => $this->blockFactory
+        ]);
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage Invalid Data Source class name: NotExistingBlockClass
+     */
+    public function testAddWithException()
+    {
+        $this->dataSourcePool->add('DataSourcePoolTestBlock', 'NotExistingBlockClass');
+    }
+
+    protected function createBlock($blockClass)
+    {
+        $block = $this->getMock('Magento\Framework\View\Element\BlockInterface');
+
+        $this->blockFactory->expects($this->once())
+            ->method('createBlock')
+            ->with($blockClass)
+            ->will($this->returnValue($block));
+        return $block;
+    }
+
+    public function testAdd()
+    {
+        $blockName = 'DataSourcePoolTestBlock';
+        $blockClass = 'Magento\Framework\View\DataSourcePoolTestBlock';
+
+        $block = $this->createBlock($blockClass);
+
+        $this->assertSame($block, $this->dataSourcePool->add($blockName, $blockClass));
+    }
+
+    public function testGet()
+    {
+        $blockName = 'DataSourcePoolTestBlock';
+        $blockClass = 'Magento\Framework\View\DataSourcePoolTestBlock';
+
+        $block = $this->createBlock($blockClass);
+        $this->dataSourcePool->add($blockName, $blockClass);
+
+        $this->assertSame($block, $this->dataSourcePool->get($blockName));
+        $this->assertEquals([$blockName => $block], $this->dataSourcePool->get());
+        $this->assertNull($this->dataSourcePool->get('WrongName'));
+    }
+
+    public function testGetEmpty()
+    {
+        $this->assertEquals([], $this->dataSourcePool->get());
+    }
+
+    public function testAssignAndGetNamespaceData()
+    {
+        $blockName = 'DataSourcePoolTestBlock';
+        $blockClass = 'Magento\Framework\View\DataSourcePoolTestBlock';
+
+        $block = $this->createBlock($blockClass);
+        $this->dataSourcePool->add($blockName, $blockClass);
+
+        $namespace = 'namespace';
+        $alias = 'alias';
+        $this->dataSourcePool->assign($blockName, $namespace, $alias);
+
+        $this->assertEquals(['alias' => $block], $this->dataSourcePool->getNamespaceData($namespace));
+        $this->assertEquals([], $this->dataSourcePool->getNamespaceData('WrongNamespace'));
+    }
+}
+
+/**
+ * Class DataSourcePoolTestBlock mock
+ */
+class DataSourcePoolTestBlock implements \Magento\Framework\View\Element\BlockInterface
+{
+    /**
+     * Produce and return block's html output
+     *
+     * @return string
+     */
+    public function toHtml()
+    {
+        return '';
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/DesignExceptionsTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/DesignExceptionsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..773bf22d8e7c31aaf2e487335baa257049a4e0a1
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/DesignExceptionsTest.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\View;
+
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+
+class DesignExceptionsTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Framework\View\DesignExceptions */
+    protected $designExceptions;
+
+    /** @var ObjectManagerHelper */
+    protected $objectManagerHelper;
+
+    /** @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $scopeConfigMock;
+
+    /** @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject */
+    protected $requestMock;
+
+    /** @var string */
+    protected $exceptionConfigPath = 'exception_path';
+
+    /** @var string */
+    protected $scopeType = 'scope_type';
+
+    protected function setUp()
+    {
+        $this->scopeConfigMock = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface');
+        $this->requestMock = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false);
+
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->designExceptions = $this->objectManagerHelper->getObject(
+            'Magento\Framework\View\DesignExceptions',
+            [
+                'scopeConfig' => $this->scopeConfigMock,
+                'exceptionConfigPath' => $this->exceptionConfigPath,
+                'scopeType' => $this->scopeType
+            ]
+        );
+    }
+
+    /**
+     * @param string $userAgent
+     * @param bool $useConfig
+     * @param bool|string $result
+     * @param array $expressions
+     * @dataProvider getThemeByRequestDataProvider
+     */
+    public function testGetThemeByRequest($userAgent, $useConfig, $result, $expressions = [])
+    {
+        $this->requestMock->expects($this->once())
+            ->method('getServer')
+            ->with($this->equalTo('HTTP_USER_AGENT'))
+            ->will($this->returnValue($userAgent));
+
+        if ($useConfig) {
+            $this->scopeConfigMock->expects($this->once())
+                ->method('getValue')
+                ->with($this->equalTo($this->exceptionConfigPath), $this->equalTo($this->scopeType))
+                ->will($this->returnValue(serialize($expressions)));
+        }
+
+        $this->assertSame($result, $this->designExceptions->getThemeByRequest($this->requestMock));
+    }
+
+    /**
+     * @return array
+     */
+    public function getThemeByRequestDataProvider()
+    {
+        return [
+            [false, false, false],
+            ['iphone', false, false],
+            ['iphone', true, false],
+            ['iphone', true, 'matched', [['regexp' => '/iphone/', 'value' => 'matched']]],
+            ['explorer', true, false, [['regexp' => '/iphone/', 'value' => 'matched']]],
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/Element/BlockFactoryTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/Element/BlockFactoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..cd42c5994545513fb918abda0119c19e7dba11b2
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/Element/BlockFactoryTest.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\View\Element;
+
+class BlockFactoryTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\View\Element\BlockFactory
+     */
+    protected $blockFactory;
+
+    /**
+     * @var \Magento\Framework\ObjectManager|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $objectManagerMock;
+
+    public function setUp()
+    {
+        $objectManagerHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
+
+        $this->objectManagerMock = $this->getMockBuilder('Magento\Framework\ObjectManager')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->blockFactory = $objectManagerHelper->getObject('Magento\Framework\View\Element\BlockFactory', array(
+            'objectManager' => $this->objectManagerMock
+        ));
+    }
+
+    public function testCreateBlock()
+    {
+        $className = 'Magento\Framework\View\Element\Template';
+        $argumentsResult = ['arg1', 'arg2'];
+
+        $templateMock = $this->getMockBuilder('Magento\Framework\View\Element\Template')
+            ->disableOriginalConstructor()->getMock();
+
+        $this->objectManagerMock->expects($this->once())
+            ->method('create')
+            ->with($className, $argumentsResult)
+            ->will($this->returnValue($templateMock));
+
+        $this->assertInstanceOf(
+            'Magento\Framework\View\Element\BlockInterface',
+            $this->blockFactory->createBlock($className, $argumentsResult)
+        );
+    }
+
+    /**
+     * @expectedException \LogicException
+     */
+    public function testCreateBlockWithException()
+    {
+        $this->blockFactory->createBlock('invalid_class_name');
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/Element/FormKeyTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/Element/FormKeyTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..979eb53377948e440262b102e6f99ff54d2cad30
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/Element/FormKeyTest.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\View\Element;
+
+class FormKeyTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\View\Element\FormKey
+     */
+    protected $formKeyElement;
+
+    protected function setUp()
+    {
+        $objectManagerHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
+
+        $formKeyMock = $this->getMockBuilder('Magento\Framework\Data\Form\FormKey')
+            ->setMethods(['getFormKey'])->disableOriginalConstructor()->getMock();
+
+        $formKeyMock->expects($this->any())
+            ->method('getFormKey')
+            ->will($this->returnValue('form_key'));
+
+        $this->formKeyElement = $objectManagerHelper->getObject(
+            'Magento\Framework\View\Element\FormKey',
+            ['formKey' => $formKeyMock]
+        );
+    }
+
+    public function testGetFormKey()
+    {
+        $this->assertEquals('form_key', $this->formKeyElement->getFormKey());
+    }
+
+    public function testToHtml()
+    {
+        $this->assertEquals(
+            '<input name="form_key" type="hidden" value="form_key" />',
+            $this->formKeyElement->toHtml()
+        );
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/Element/Html/LinkTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/Element/Html/LinkTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..69f1c6cf6b77d1251582e5af9f53287d276dabda
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/Element/Html/LinkTest.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\View\Element\Html;
+
+class LinkTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var array
+     */
+    protected $allowedAttributes = [
+        'shape',
+        'tabindex',
+        'onfocus',
+        'onblur',
+        'id',
+        'some_invalid_data'
+    ];
+
+    /**
+     * @var \Magento\Framework\View\Element\Html\Link
+     */
+    protected $link;
+
+    /**
+     * @param \Magento\Framework\View\Element\Html\Link $link
+     * @param string $expected
+     *
+     * @dataProvider getLinkAttributesDataProvider
+     */
+    public function testGetLinkAttributes($link, $expected)
+    {
+        $this->assertEquals($expected, $link->getLinkAttributes());
+    }
+
+    public function getLinkAttributesDataProvider()
+    {
+        $objectManagerHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
+
+        $escaperMock = $this->getMockBuilder('Magento\Framework\Escaper')
+            ->setMethods(['escapeHtml'])->disableOriginalConstructor()->getMock();
+
+        $escaperMock->expects($this->any())
+            ->method('escapeHtml')
+            ->will($this->returnArgument(0));
+
+        $urlBuilderMock = $this->getMockBuilder('Magento\Framework\UrlInterface')
+            ->setMethods(['getUrl'])->disableOriginalConstructor()->getMockForAbstractClass();
+
+        $urlBuilderMock->expects($this->any())
+            ->method('getUrl')
+            ->will($this->returnArgument('http://site.com/link.html'));
+
+        $contextMock = $this->getMockBuilder('Magento\Framework\View\Element\Template\Context')
+            ->setMethods(['getEscaper', 'getUrlBuilder'])->disableOriginalConstructor()->getMock();
+
+        $contextMock->expects($this->any())
+            ->method('getEscaper')
+            ->will($this->returnValue($escaperMock));
+
+        $contextMock->expects($this->any())
+            ->method('getUrlBuilder')
+            ->will($this->returnValue($urlBuilderMock));
+
+        /** @var \Magento\Framework\View\Element\Html\Link $linkWithAttributes */
+        $linkWithAttributes = $objectManagerHelper->getObject(
+            'Magento\Framework\View\Element\Html\Link',
+            ['context' => $contextMock]
+        );
+        /** @var \Magento\Framework\View\Element\Html\Link $linkWithoutAttributes */
+        $linkWithoutAttributes = $objectManagerHelper->getObject(
+            'Magento\Framework\View\Element\Html\Link',
+            ['context' => $contextMock]
+        );
+
+        foreach ($this->allowedAttributes as $attribute) {
+            $linkWithAttributes->setDataUsingMethod($attribute, $attribute);
+        }
+
+        return [
+            'full' => [
+                'link' => $linkWithAttributes,
+                'expected' => 'shape="shape" tabindex="tabindex" onfocus="onfocus" onblur="onblur" id="id"'
+            ],
+            'empty' => [
+                'link' => $linkWithoutAttributes,
+                'expected' => ''
+            ],
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/Element/Html/SelectTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/Element/Html/SelectTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f74f0e07254c8bffa14b416ac68a25b21f0e3177
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/Element/Html/SelectTest.php
@@ -0,0 +1,184 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\View\Element\Html;
+
+class SelectTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Select
+     */
+    protected $select;
+
+    protected function setUp()
+    {
+        $eventManager = $this->getMock('Magento\Framework\Event\ManagerInterface');
+
+        $scopeConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface');
+
+        $escaper = $this->getMockBuilder('Magento\Framework\Escaper')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $escaper->expects($this->any())
+            ->method('escapeHtml')
+            ->will($this->returnArgument(0));
+
+        $context = $this->getMockBuilder('Magento\Framework\View\Element\Context')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $context->expects($this->once())
+            ->method('getEscaper')
+            ->will($this->returnValue($escaper));
+        $context->expects($this->once())
+            ->method('getEventManager')
+            ->will($this->returnValue($eventManager));
+        $context->expects($this->once())
+            ->method('getScopeConfig')
+            ->will($this->returnValue($scopeConfig));
+
+        $objectManagerHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->select = $objectManagerHelper->getObject('Magento\Framework\View\Element\Html\Select', [
+            'context' => $context
+        ]);
+    }
+
+    public function testAddOptionAndSetOptionsAndGetOptions()
+    {
+        $value = 'testValue';
+        $label = 'testLabel';
+        $params = ['paramKey' => 'paramValue'];
+
+        $options = [['value' => $value, 'label' => $label, 'params' => $params]];
+
+        $this->assertEquals([], $this->select->getOptions());
+
+        $this->select->addOption($value, $label, $params);
+        $this->assertEquals($options, $this->select->getOptions());
+
+        $options[0]['value'] = 'newValue';
+        $this->select->setOptions($options);
+        $this->assertEquals($options, $this->select->getOptions());
+    }
+
+    public function testGetSetId()
+    {
+        $selectId = 'testId';
+
+        $this->assertNull($this->select->getId());
+        $this->select->setId($selectId);
+        $this->assertEquals($selectId, $this->select->getId());
+    }
+
+    public function testGetSetClass()
+    {
+        $selectClass = 'testClass';
+
+        $this->assertNull($this->select->getClass());
+        $this->select->setClass($selectClass);
+        $this->assertEquals($selectClass, $this->select->getClass());
+    }
+
+    public function testGetSetTitle()
+    {
+        $selectTitle = 'testTitle';
+
+        $this->assertNull($this->select->getTitle());
+        $this->select->setTitle($selectTitle);
+        $this->assertEquals($selectTitle, $this->select->getTitle());
+    }
+
+    public function testGetHtml()
+    {
+        $selectId = 'testId';
+        $selectClass = 'testClass';
+        $selectTitle = 'testTitle';
+        $selectName = 'testName';
+
+        $value = 'testValue';
+        $label = 'testLabel';
+        $params = ['paramKey' => 'paramValue'];
+
+        $valueGroup = [
+            'groupElementValue' => 'GroupElementLabel',
+            'selectedGroupElementValue' => 'SelectedGroupElementLabel'
+        ];
+        $labelGroup = 'groupLabel';
+
+        $selectedValue = 'selectedValue';
+        $selectedLabel = 'selectedLabel';
+        $selectedParams = [['paramKey' => 'paramValue', 'paramKey2' => 'paramValue2']];
+
+        $selectedValues = [$selectedValue, 'selectedGroupElementValue'];
+
+        $this->select->setId($selectId);
+        $this->select->setClass($selectClass);
+        $this->select->setTitle($selectTitle);
+        $this->select->setName($selectName);
+        $this->select->addOption($value, $label, $params);
+        $this->select->addOption($selectedValue, $selectedLabel, $selectedParams);
+        $this->select->addOption($valueGroup, $labelGroup);
+        $this->select->setValue($selectedValues);
+
+        $result = '<select name="testName" id="testId" class="testClass" title="testTitle" >'
+            .   '<option value="testValue"  paramKey="paramValue" >testLabel</option>'
+            .   '<option value="selectedValue" selected="selected"  paramKey="paramValue" '
+            .       ' paramKey2="paramValue2" >selectedLabel</option>'
+            .   '<optgroup label="groupLabel">'
+            .       '<option value="groupElementValue" >GroupElementLabel</option>'
+            .       '<option value="selectedGroupElementValue" selected="selected" >SelectedGroupElementLabel</option>'
+            .   '</optgroup>'
+            . '</select>';
+
+        $this->assertEquals($result, $this->select->getHtml());
+    }
+
+    public function testGetHtmlJs()
+    {
+        $selectId = 'testId';
+        $selectClass = 'testClass';
+        $selectTitle = 'testTitle';
+        $selectName = 'testName';
+
+
+        $options = [
+            'testValue' => 'testLabel',
+            'selectedValue' => 'selectedLabel',
+        ];
+        $selectedValue = 'selectedValue';
+
+        $this->select->setId($selectId);
+        $this->select->setClass($selectClass);
+        $this->select->setTitle($selectTitle);
+        $this->select->setName($selectName);
+        $this->select->setOptions($options);
+        $this->select->setValue($selectedValue);
+
+        $result = '<select name="testName" id="testId" class="testClass" title="testTitle" >'
+            . '<option value="testValue" #{option_extra_attr_4016862802} >testLabel</option>'
+            . '<option value="selectedValue" selected="selected" #{option_extra_attr_662265145} >selectedLabel</option>'
+            . '</select>';
+
+        $this->select->setIsRenderToJsTemplate(true);
+        $this->assertEquals($result, $this->select->getHtml());
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/Element/MessagesTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/Element/MessagesTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b49955c17ff3ba6d7ecb881270eb583faf3daa62
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/Element/MessagesTest.php
@@ -0,0 +1,251 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/**
+ * Test for view Messages model
+ */
+namespace Magento\Framework\View\Element;
+
+use Magento\Framework\Message\MessageInterface;
+use Magento\Framework\Message\ManagerInterface;
+
+class MessagesTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Messages
+     */
+    protected $messages;
+
+    /**
+     * @var \Magento\Framework\Message\Factory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $messageFactory;
+
+    /**
+     * @var \Magento\Framework\Message\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $collectionFactory;
+
+    protected function setUp()
+    {
+        $this->collectionFactory = $this->getMockBuilder('Magento\Framework\Message\CollectionFactory')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->messageFactory = $this->getMockBuilder('Magento\Framework\Message\Factory')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->messages = $objectManager->getObject('Magento\Framework\View\Element\Messages', [
+            'collectionFactory' => $this->collectionFactory,
+            'messageFactory' => $this->messageFactory
+        ]);
+    }
+
+    /**
+     * @return \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Message\Collection
+     */
+    protected function initMessageCollection()
+    {
+        $collection = $this->getMockBuilder('Magento\Framework\Message\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->collectionFactory->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($collection));
+        return $collection;
+    }
+
+    public function testSetMessages()
+    {
+        $collection = $this->getMockBuilder('Magento\Framework\Message\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->collectionFactory->expects($this->never())->method('create');
+
+        $this->messages->setMessages($collection);
+        $this->assertSame($collection, $this->messages->getMessageCollection());
+    }
+
+    public function testGetMessageCollection()
+    {
+        $collection = $this->initMessageCollection();
+
+        $this->assertSame($collection, $this->messages->getMessageCollection());
+    }
+
+    public function testAddMessages()
+    {
+        $messageOne = $this->getMock('Magento\Framework\Message\MessageInterface');
+        $messageTwo = $this->getMock('Magento\Framework\Message\MessageInterface');
+
+        $arrayMessages = [$messageOne, $messageTwo];
+
+        $collection = $this->initMessageCollection();
+
+        $collection->expects($this->at(0))
+            ->method('addMessage')
+            ->with($messageOne);
+        $collection->expects($this->at(1))
+            ->method('addMessage')
+            ->with($messageTwo);
+
+        $collectionForAdd = $this->getMockBuilder('Magento\Framework\Message\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $collectionForAdd->expects($this->atLeastOnce())
+            ->method('getItems')
+            ->will($this->returnValue($arrayMessages));
+
+        $this->assertSame($this->messages, $this->messages->addMessages($collectionForAdd));
+    }
+
+    public function testAddMessage()
+    {
+        $message = $this->getMock('Magento\Framework\Message\MessageInterface');
+
+        $collection = $this->initMessageCollection();
+
+        $collection->expects($this->once())
+            ->method('addMessage')
+            ->with($message);
+
+        $this->assertSame($this->messages, $this->messages->addMessage($message));
+    }
+
+    public function testAddError()
+    {
+        $messageText = 'Some message error text';
+
+        $message = $this->getMock('Magento\Framework\Message\MessageInterface');
+
+        $this->messageFactory->expects($this->once())
+            ->method('create')
+            ->with(MessageInterface::TYPE_ERROR, $messageText)
+            ->will($this->returnValue($message));
+
+        $collection = $this->initMessageCollection();
+        $collection->expects($this->once())
+            ->method('addMessage')
+            ->with($message);
+
+        $this->assertSame($this->messages, $this->messages->addError($messageText));
+    }
+
+    public function testAddWarning()
+    {
+        $messageText = 'Some message warning text';
+
+        $message = $this->getMock('Magento\Framework\Message\MessageInterface');
+
+        $this->messageFactory->expects($this->once())
+            ->method('create')
+            ->with(MessageInterface::TYPE_WARNING, $messageText)
+            ->will($this->returnValue($message));
+
+        $collection = $this->initMessageCollection();
+        $collection->expects($this->once())
+            ->method('addMessage')
+            ->with($message);
+
+        $this->assertSame($this->messages, $this->messages->addWarning($messageText));
+    }
+
+    public function testAddNotice()
+    {
+        $messageText = 'Some message notice text';
+
+        $message = $this->getMock('Magento\Framework\Message\MessageInterface');
+
+        $this->messageFactory->expects($this->once())
+            ->method('create')
+            ->with(MessageInterface::TYPE_NOTICE, $messageText)
+            ->will($this->returnValue($message));
+
+        $collection = $this->initMessageCollection();
+        $collection->expects($this->once())
+            ->method('addMessage')
+            ->with($message);
+
+        $this->assertSame($this->messages, $this->messages->addNotice($messageText));
+    }
+
+    public function testAddSuccess()
+    {
+        $messageText = 'Some message success text';
+
+        $message = $this->getMock('Magento\Framework\Message\MessageInterface');
+
+        $this->messageFactory->expects($this->once())
+            ->method('create')
+            ->with(MessageInterface::TYPE_SUCCESS, $messageText)
+            ->will($this->returnValue($message));
+
+        $collection = $this->initMessageCollection();
+        $collection->expects($this->once())
+            ->method('addMessage')
+            ->with($message);
+
+        $this->assertSame($this->messages, $this->messages->addSuccess($messageText));
+    }
+
+    public function testGetMessagesByType()
+    {
+        $messageType = MessageInterface::TYPE_SUCCESS;
+        $resultMessages = [$this->getMock('Magento\Framework\Message\MessageInterface')];
+
+        $collection = $this->initMessageCollection();
+        $collection->expects($this->once())
+            ->method('getItemsByType')
+            ->with($messageType)
+            ->will($this->returnValue($resultMessages));
+
+        $this->assertSame($resultMessages, $this->messages->getMessagesByType($messageType));
+    }
+
+    public function testGetMessageTypes()
+    {
+        $types = array(
+            MessageInterface::TYPE_ERROR,
+            MessageInterface::TYPE_WARNING,
+            MessageInterface::TYPE_NOTICE,
+            MessageInterface::TYPE_SUCCESS
+        );
+        $this->assertEquals($types, $this->messages->getMessageTypes());
+    }
+
+    public function testGetCacheKeyInfo()
+    {
+        $emptyMessagesCacheKey = ['storage_types' => 'a:0:{}'];
+        $this->assertEquals($emptyMessagesCacheKey, $this->messages->getCacheKeyInfo());
+
+        $messagesCacheKey = ['storage_types' => 'a:1:{i:0;s:7:"default";}'];
+        $this->messages->addStorageType(ManagerInterface::DEFAULT_GROUP);
+        $this->assertEquals($messagesCacheKey, $this->messages->getCacheKeyInfo());
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/Element/RendererListTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/Element/RendererListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..de0a7e563c9867a6f143607467f6a24cce55ef37
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/Element/RendererListTest.php
@@ -0,0 +1,116 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\View\Element;
+
+class RendererListTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\View\Element\RendererList
+     */
+    protected $renderList;
+
+    /**
+     * @var \Magento\Framework\View\Element\Context|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $contextMock;
+
+    /**
+     * @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $layoutMock;
+
+    /**
+     * @var \Magento\Framework\View\Element\AbstractBlock|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $blockMock;
+
+    protected function setUp()
+    {
+        $objectManagerHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
+
+        $this->blockMock = $this->getMockBuilder('Magento\Framework\View\Element\AbstractBlock')
+            ->setMethods(['setRenderedBlock', 'getTemplate', 'setTemplate'])->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $this->layoutMock = $this->getMockBuilder('Magento\Framework\View\LayoutInterface')
+            ->setMethods(['getBlock', 'getChildName'])->disableOriginalConstructor()->getMockForAbstractClass();
+
+        $this->layoutMock->expects($this->any())
+            ->method('getBlock')
+            ->will($this->returnValue($this->blockMock));
+
+        $this->contextMock = $this->getMockBuilder('Magento\Framework\View\Element\Context')
+            ->setMethods(['getLayout'])->disableOriginalConstructor()->getMock();
+
+        $this->contextMock->expects($this->any())
+            ->method('getLayout')
+            ->will($this->returnValue($this->layoutMock));
+
+        $this->renderList = $objectManagerHelper->getObject(
+            'Magento\Framework\View\Element\RendererList',
+            ['context' => $this->contextMock]
+        );
+    }
+
+    public function testGetRenderer()
+    {
+        $this->blockMock->expects($this->any())
+            ->method('setRenderedBlock')
+            ->will($this->returnValue($this->blockMock));
+
+        $this->blockMock->expects($this->any())
+            ->method('getTemplate')
+            ->will($this->returnValue('template'));
+
+        $this->blockMock->expects($this->any())
+            ->method('setTemplate')
+            ->will($this->returnValue($this->blockMock));
+
+        $this->layoutMock->expects($this->any())
+            ->method('getChildName')
+            ->will($this->returnValue(true));
+
+        /** During the first call cache will be generated */
+        $this->assertInstanceOf(
+            '\Magento\Framework\View\Element\BlockInterface',
+            $this->renderList->getRenderer('type', null, null)
+        );
+        /** Cached value should be returned during second call */
+        $this->assertInstanceOf(
+            '\Magento\Framework\View\Element\BlockInterface',
+            $this->renderList->getRenderer('type', null, 'renderer_template')
+        );
+    }
+
+    /**
+     * @expectedException \RuntimeException
+     */
+    public function testGetRendererWithException()
+    {
+        $this->assertInstanceOf(
+            '\Magento\Framework\View\Element\BlockInterface',
+            $this->renderList->getRenderer(null)
+        );
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/Element/Text/TextList/ItemTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/Element/Text/TextList/ItemTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..478add800fd09307758add53927caf20cbcf6957
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/Element/Text/TextList/ItemTest.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/**
+ * Test for view BlockPool model
+ */
+namespace Magento\Framework\View\Element\Text\TextList;
+
+class ItemTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Item
+     */
+    protected $item;
+
+    protected function setUp()
+    {
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->item = $objectManager->getObject('Magento\Framework\View\Element\Text\TextList\Item');
+    }
+
+    public function testSetLink()
+    {
+        $liParams = ['class' => 'some-css-class'];
+        $innerText = 'text';
+
+        $this->assertNull($this->item->getLiParams());
+        $this->assertNull($this->item->getInnerText());
+
+        $this->item->setLink($liParams, $innerText);
+
+        $this->assertEquals($liParams, $this->item->getLiParams());
+        $this->assertEquals($innerText, $this->item->getInnerText());
+    }
+
+    /**
+     * @dataProvider toHtmlDataProvider
+     */
+    public function testToHtml($liParams, $attrName, $attrValue, $innerText)
+    {
+        $this->item->setLink($liParams, $innerText);
+        $this->assertTag([
+            'tag' => 'li',
+            'attributes' => [$attrName => $attrValue],
+            'content' => $innerText
+        ], $this->item->toHtml());
+    }
+
+    public function toHtmlDataProvider()
+    {
+        return [
+            [
+                'liParams' => ['class' => 'some-css-class'],
+                'attrName' => 'class',
+                'attrValue' => 'some-css-class',
+                'innerText' => 'text',
+            ], [
+                'liParams' => 'class="some-css-class"',
+                'attrName' => 'class',
+                'attrValue' => 'some-css-class',
+                'innerText' => 'text',
+            ]
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/Element/Text/TextList/LinkTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/Element/Text/TextList/LinkTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d78182eb8926d23af2cb5c076821a53846576464
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/Element/Text/TextList/LinkTest.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/**
+ * Test for view BlockPool model
+ */
+namespace Magento\Framework\View\Element\Text\TextList;
+
+class LinkTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Link
+     */
+    protected $link;
+
+    protected function setUp()
+    {
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->link = $objectManager->getObject('Magento\Framework\View\Element\Text\TextList\Link');
+    }
+
+    public function testSetLink()
+    {
+        $liParams = ['class' => 'some-css-class'];
+        $aParams = ['href' => 'url'];
+        $innerText = 'text';
+        $afterText = 'afterText';
+
+        $this->assertNull($this->link->getLiParams());
+        $this->assertNull($this->link->getAParams());
+        $this->assertNull($this->link->getInnerText());
+        $this->assertNull($this->link->getAfterText());
+
+        $this->link->setLink($liParams, $aParams, $innerText, $afterText);
+
+        $this->assertEquals($liParams, $this->link->getLiParams());
+        $this->assertEquals($aParams, $this->link->getAParams());
+        $this->assertEquals($innerText, $this->link->getInnerText());
+        $this->assertEquals($afterText, $this->link->getAfterText());
+    }
+
+    /**
+     * @dataProvider toHtmlDataProvider
+     */
+    public function testToHtml($liParams, $liAttr, $aParams, $aAttr, $innerText, $afterText)
+    {
+        $this->link->setLink($liParams, $aParams, $innerText, $afterText);
+        $this->assertTag([
+            'tag' => 'li',
+            'attributes' => [$liAttr['name'] => $liAttr['value']],
+            'child' => [
+                'tag' => 'a',
+                'attributes' => [$aAttr['name'] => $aAttr['value']],
+                'content' => $innerText
+            ],
+            'content' => $afterText
+        ], $this->link->toHtml());
+    }
+
+    public function toHtmlDataProvider()
+    {
+        return [
+            [
+                'liParams' => ['class' => 'some-css-class'],
+                'liAttr' => ['name' => 'class', 'value' => 'some-css-class'],
+                'aParams' => ['href' => 'url'],
+                'aAttr' => ['name' => 'href', 'value' => 'url'],
+                'innerText' => 'text',
+                'afterText' => 'afterText',
+            ],
+            [
+                'liParams' => 'class="some-css-class"',
+                'liAttr' => ['name' => 'class', 'value' => 'some-css-class'],
+                'aParams' => 'href="url"',
+                'aAttr' => ['name' => 'href', 'value' => 'url'],
+                'innerText' => 'text',
+                'afterText' => 'afterText',
+            ]
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/Element/TextTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/Element/TextTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c8fc6a1e448dc3d9ef6edf4e4a78af2a782539df
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/Element/TextTest.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\View\Element;
+
+class TextTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\View\Element\Text
+     */
+    protected $elementText;
+
+    protected function setUp()
+    {
+        $objectManagerHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->elementText = $objectManagerHelper->getObject('Magento\Framework\View\Element\Text');
+
+    }
+
+    public function testSetText()
+    {
+        $this->assertInstanceOf('Magento\Framework\View\Element\Text', $this->elementText->setText('example'));
+    }
+
+    public function testGetText()
+    {
+        $this->elementText->setText('example');
+        $this->assertEquals('example', $this->elementText->getText('example'));
+    }
+
+    /**
+     * @param string $text
+     * @param bool $before
+     * @param string $expectedResult
+     *
+     * @dataProvider addTextDataProvider
+     */
+    public function testAddText($text, $before, $expectedResult)
+    {
+        $this->elementText->setText('example');
+        $this->elementText->addText($text, $before);
+        $this->assertEquals($expectedResult, $this->elementText->getText('example'));
+    }
+
+    /**
+     * @return array
+     */
+    public function addTextDataProvider()
+    {
+        return [
+            'before_false' => [
+                'text' => '_after',
+                'before' => false,
+                'expectedResult' => 'example_after'
+            ],
+            'before_true' => [
+                'text' => 'before_',
+                'before' => true,
+                'expectedResult' => 'before_example'
+            ],
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/LayoutFactoryTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/LayoutFactoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a1c699c350e0d0ce7853af7bbca06a7523f690b4
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/LayoutFactoryTest.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\View;
+
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+
+class LayoutFactoryTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Framework\View\LayoutFactory */
+    protected $layoutFactory;
+
+    /** @var ObjectManagerHelper */
+    protected $objectManagerHelper;
+
+    /** @var \Magento\Framework\ObjectManager|\PHPUnit_Framework_MockObject_MockObject */
+    protected $objectManagerMock;
+
+    protected function setUp()
+    {
+        $this->objectManagerMock = $this->getMock('Magento\Framework\ObjectManager');
+
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->layoutFactory = $this->objectManagerHelper->getObject(
+            'Magento\Framework\View\LayoutFactory',
+            [
+                'objectManager' => $this->objectManagerMock
+            ]
+        );
+    }
+
+    public function testCreate()
+    {
+        $instance = 'Magento\Framework\View\LayoutInterface';
+        $layoutMock = $this->getMock($instance, [], [], '', false);
+        $data = ['some' => 'data'];
+        $this->objectManagerMock->expects($this->once())
+            ->method('create')
+            ->with($this->equalTo($instance), $this->equalTo($data))
+            ->will($this->returnValue($layoutMock));
+        $this->assertInstanceOf($instance, $this->layoutFactory->create($data));
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage stdClass must be an instance of LayoutInterface.
+     */
+    public function testCreateException()
+    {
+        $data = ['some' => 'other_data'];
+        $this->objectManagerMock->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue(new \stdClass()));
+        $this->layoutFactory->create($data);
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/LayoutTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/LayoutTest.php
index 67704dd9d191cd2a556f67d203871cbf940780c0..260008d98e0258c4728f8db00067ccb3ac1bbfc7 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/View/LayoutTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/LayoutTest.php
@@ -23,22 +23,25 @@
  */
 namespace Magento\Framework\View;
 
+/**
+ * Class LayoutTest
+ */
 class LayoutTest extends \PHPUnit_Framework_TestCase
 {
     /**
      * @var \Magento\Framework\View\Layout
      */
-    protected $_model;
+    protected $model;
 
     /**
      * @var \PHPUnit_Framework_MockObject_MockObject
      */
-    protected $_structureMock;
+    protected $structureMock;
 
     /**
      * @var \PHPUnit_Framework_MockObject_MockObject
      */
-    protected $_blockFactoryMock;
+    protected $blockFactoryMock;
 
     /**
      * @var \Magento\Framework\View\Layout\ProcessorFactory|\PHPUnit_Framework_MockObject_MockObject
@@ -60,18 +63,25 @@ class LayoutTest extends \PHPUnit_Framework_TestCase
      */
     protected $processorMock;
 
+    /**
+     * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $eventManagerMock;
+
+    /**
+     * @var \Magento\Framework\View\Layout\ScheduledStructure|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $schStructureMock;
+
     protected function setUp()
     {
-        $this->_structureMock = $this->getMockBuilder(
-            'Magento\Framework\Data\Structure'
-        )->setMethods(
-            array('createElement')
-        )->disableOriginalConstructor()->getMock();
-        $this->_blockFactoryMock = $this->getMockBuilder(
-            'Magento\Framework\View\Element\BlockFactory'
-        )->setMethods(
-            array('createBlock')
-        )->disableOriginalConstructor()->getMock();
+        $this->structureMock = $this->getMockBuilder('Magento\Framework\Data\Structure')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->blockFactoryMock = $this->getMockBuilder('Magento\Framework\View\Element\BlockFactory')
+            ->setMethods(['createBlock'])
+            ->disableOriginalConstructor()
+            ->getMock();
         $this->processorFactoryMock = $this->getMock(
             'Magento\Framework\View\Layout\ProcessorFactory',
             ['create'],
@@ -79,33 +89,25 @@ class LayoutTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->appStateMock = $this->getMock(
-            'Magento\Framework\App\State',
-            [],
-            [],
-            '',
-            false
-        );
+        $this->appStateMock = $this->getMock('Magento\Framework\App\State', [], [], '', false);
         $this->themeResolverMock = $this->getMockForAbstractClass(
             'Magento\Framework\View\Design\Theme\ResolverInterface'
         );
-        $this->processorMock = $this->getMock(
-            'Magento\Core\Model\Layout\Merge',
-            ['__destruct'],
-            [],
-            '',
-            false
-        );
+        $this->processorMock = $this->getMock('Magento\Core\Model\Layout\Merge', [], [], '', false);
+        $this->schStructureMock = $this->getMock('Magento\Framework\View\Layout\ScheduledStructure', [], [], '', false);
+        $this->eventManagerMock = $this->getMock('Magento\Framework\Event\ManagerInterface');
 
         $objectManagerHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $this->_model = $objectManagerHelper->getObject(
+        $this->model = $objectManagerHelper->getObject(
             'Magento\Framework\View\Layout',
             array(
-                'structure' => $this->_structureMock,
-                'blockFactory' => $this->_blockFactoryMock,
+                'structure' => $this->structureMock,
+                'blockFactory' => $this->blockFactoryMock,
                 'themeResolver' => $this->themeResolverMock,
                 'processorFactory' => $this->processorFactoryMock,
                 'appState' => $this->appStateMock,
+                'eventManager' => $this->eventManagerMock,
+                'scheduledStructure' => $this->schStructureMock
             )
         );
     }
@@ -115,43 +117,600 @@ class LayoutTest extends \PHPUnit_Framework_TestCase
      */
     public function testCreateBlockException()
     {
-        $this->_model->createBlock('type', 'blockname', array());
+        $this->model->createBlock('type', 'blockname', array());
     }
 
     public function testCreateBlockSuccess()
     {
-        $blockMock = $this->getMockBuilder(
-            'Magento\Framework\View\Element\AbstractBlock'
-        )->disableOriginalConstructor()->getMockForAbstractClass();
-        $this->_blockFactoryMock->expects($this->once())->method('createBlock')->will($this->returnValue($blockMock));
+        $blockMock = $this->getMockBuilder('Magento\Framework\View\Element\AbstractBlock')
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+        $this->blockFactoryMock->expects($this->once())->method('createBlock')->will($this->returnValue($blockMock));
 
-        $this->_model->createBlock('type', 'blockname', array());
-        $this->assertInstanceOf('Magento\Framework\View\Element\AbstractBlock', $this->_model->getBlock('blockname'));
+        $this->model->createBlock('type', 'blockname', array());
+        $this->assertInstanceOf('Magento\Framework\View\Element\AbstractBlock', $this->model->getBlock('blockname'));
+        $this->assertFalse($this->model->getBlock('not_exist'));
     }
 
     public function testGetUpdate()
     {
         $themeMock = $this->getMockForAbstractClass('Magento\Framework\View\Design\ThemeInterface');
 
-        $this->themeResolverMock->expects(
-            $this->once()
-        )->method(
-            'get'
-        )->will(
-            $this->returnValue($themeMock)
-        );
+        $this->themeResolverMock->expects($this->once())
+            ->method('get')
+            ->will($this->returnValue($themeMock));
+
+        $this->processorFactoryMock->expects($this->once())
+            ->method('create')
+            ->with(array('theme' => $themeMock))
+            ->will($this->returnValue($this->processorMock));
+
+        $this->assertEquals($this->processorMock, $this->model->getUpdate());
+        $this->assertEquals($this->processorMock, $this->model->getUpdate());
+    }
+
+    public function testGenerateXml()
+    {
+        $themeMock = $this->getMockForAbstractClass('Magento\Framework\View\Design\ThemeInterface');
+
+        $this->themeResolverMock->expects($this->once())
+            ->method('get')
+            ->will($this->returnValue($themeMock));
+
+        $this->processorFactoryMock->expects($this->once())
+            ->method('create')
+            ->with(array('theme' => $themeMock))
+            ->will($this->returnValue($this->processorMock));
+
+        $xmlString = '<?xml version="1.0"?><layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
+            . '<some_update>123</some_update></layout>';
+        $xml = simplexml_load_string($xmlString, 'Magento\Framework\View\Layout\Element');
+        $this->processorMock->expects($this->once())
+            ->method('asSimplexml')
+            ->will($this->returnValue($xml));
+
+        $this->structureMock->expects($this->once())
+            ->method('importElements')
+            ->with($this->equalTo([]))
+            ->will($this->returnSelf());
+        $this->assertSame($this->model, $this->model->generateXml());
+        $this->assertSame('<some_update>123</some_update>', $this->model->getNode('some_update')->asXml());
+    }
+
+    /**
+     * @param string $parentName
+     * @param string $alias
+     * @param string $name
+     * @param bool $isBlock
+     * @dataProvider getChildBlockDataProvider
+     */
+    public function testGetChildBlock($parentName, $alias, $name, $isBlock)
+    {
+        $this->structureMock->expects($this->once())
+            ->method('getChildId')
+            ->with($this->equalTo($parentName), $this->equalTo($alias))
+            ->will($this->returnValue($name));
+        $this->structureMock->expects($this->once())
+            ->method('hasElement')
+            ->with($this->equalTo($name))
+            ->will($this->returnValue($isBlock));
+        if ($isBlock) {
+            $this->schStructureMock->expects($this->once())
+                ->method('hasElement')
+                ->with($this->equalTo($name))
+                ->will($this->returnValue($isBlock));
+            $this->structureMock->expects($this->once())
+                ->method('getAttribute')
+                ->with($this->equalTo($name), $this->equalTo('type'))
+                ->will($this->returnValue(\Magento\Framework\View\Layout\Element::TYPE_BLOCK));
+            $this->prepareGenerateBlock($name);
+            $this->assertInstanceOf(
+                'Magento\Framework\View\Element\AbstractBlock',
+                $this->model->getChildBlock($parentName, $alias)
+            );
+        } else {
+            $this->assertFalse($this->model->getChildBlock($parentName, $alias));
+        }
+    }
+
+    /**
+     * @return array
+     */
+    public function getChildBlockDataProvider()
+    {
+        return [
+            ['parent_name', 'alias', 'block_name', true],
+            ['parent_name', 'alias', 'block_name', false]
+        ];
+    }
 
-        $this->processorFactoryMock->expects(
-            $this->once()
-        )->method(
-            'create'
-        )->with(
-            array('theme' => $themeMock)
-        )->will(
-            $this->returnValue($this->processorMock)
+    /**
+     * @param string $name
+     */
+    protected function prepareGenerateBlock($name)
+    {
+        $blockClass = 'Magento\Framework\View\Element\Template';
+        $template = 'file.phtml';
+        $ttl = 100;
+        $xmlString = '<?xml version="1.0"?><block class="' . $blockClass . '" template="' . $template
+            . '" ttl="' . $ttl . '"></block>';
+        $xml = simplexml_load_string($xmlString, 'Magento\Framework\View\Layout\Element');
+        $elementData = [\Magento\Framework\View\Layout\Element::TYPE_BLOCK, $xml, [], []];
+        $this->schStructureMock->expects($this->once())
+            ->method('getElement')
+            ->with($this->equalTo($name))
+            ->will($this->returnValue($elementData));
+        $this->schStructureMock->expects($this->once())
+            ->method('unsetElement')
+            ->with($this->equalTo($name))
+            ->will($this->returnSelf());
+        $blockMock = $this->getMockBuilder('Magento\Framework\View\Element\Template')
+            ->setMethods(['setType', 'setNameInLayout', 'addData', 'setLayout', 'setTemplate', 'setTtl'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $blockMock->expects($this->once())
+            ->method('setTemplate')
+            ->with($this->equalTo($template))
+            ->will($this->returnSelf());
+        $blockMock->expects($this->once())
+            ->method('setTtl')
+            ->with($this->equalTo($ttl))
+            ->will($this->returnSelf());
+        $blockMock->expects($this->once())
+            ->method('setType')
+            ->with($this->equalTo(get_class($blockMock)))
+            ->will($this->returnSelf());
+        $blockMock->expects($this->once())
+            ->method('setNameInLayout')
+            ->with($this->equalTo($name))
+            ->will($this->returnSelf());
+        $blockMock->expects($this->once())
+            ->method('addData')
+            ->with($this->equalTo([]))
+            ->will($this->returnSelf());
+        $blockMock->expects($this->once())
+            ->method('setLayout')
+            ->with($this->equalTo($this->model))
+            ->will($this->returnSelf());
+        $this->blockFactoryMock->expects($this->once())
+            ->method('createBlock')
+            ->with($this->equalTo('Magento\Framework\View\Element\Template'), $this->equalTo(['data' => []]))
+            ->will($this->returnValue($blockMock));
+        $this->eventManagerMock->expects($this->once())
+            ->method('dispatch')
+            ->with(
+                $this->equalTo('core_layout_block_create_after'),
+                $this->equalTo(['block' => $blockMock])
+            )
+            ->will($this->returnSelf());
+    }
+
+    public function testSetChild()
+    {
+        $elementName = 'child';
+        $parentName = 'parent';
+        $alias = 'some_alias';
+        $this->structureMock->expects($this->once())
+            ->method('setAsChild')
+            ->with($this->equalTo($elementName), $this->equalTo($parentName), $this->equalTo($alias))
+            ->will($this->returnSelf());
+        $this->assertSame($this->model, $this->model->setChild($parentName, $elementName, $alias));
+    }
+
+    public function testUnsetChild()
+    {
+        $parentName = 'parent';
+        $alias = 'some_alias';
+        $this->structureMock->expects($this->once())
+            ->method('unsetChild')
+            ->with($this->equalTo($parentName), $this->equalTo($alias))
+            ->will($this->returnSelf());
+        $this->assertSame($this->model, $this->model->unsetChild($parentName, $alias));
+    }
+
+    public function testGetChildNames()
+    {
+        $parentName = 'parent';
+        $childrenArray = ['key1' => 'value1', 'key2' => 'value2'];
+        $this->structureMock->expects($this->once())
+            ->method('getChildren')
+            ->with($this->equalTo($parentName))
+            ->will($this->returnValue($childrenArray));
+        $this->assertSame(['key1', 'key2'], $this->model->getChildNames($parentName));
+    }
+
+    public function testGetChildBlocks()
+    {
+        $parentName = 'parent';
+        $childrenArray = ['block_name' => 'value1'];
+        $this->structureMock->expects($this->once())
+            ->method('getChildren')
+            ->with($this->equalTo($parentName))
+            ->will($this->returnValue($childrenArray));
+
+        $blockMock = $this->getMockBuilder('Magento\Framework\View\Element\AbstractBlock')
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+        $this->blockFactoryMock->expects($this->once())->method('createBlock')->will($this->returnValue($blockMock));
+        $this->assertSame($blockMock, $this->model->createBlock('type', 'block_name', []));
+        $this->assertSame(['value1' => $blockMock], $this->model->getChildBlocks($parentName));
+    }
+
+    public function testGetChildName()
+    {
+        $parentName = 'parent';
+        $alias = 'some_alias';
+        $this->structureMock->expects($this->once())
+            ->method('getChildId')
+            ->with($this->equalTo($parentName), $this->equalTo($alias))
+            ->will($this->returnValue('1'));
+        $this->assertSame('1', $this->model->getChildName($parentName, $alias));
+    }
+
+    public function testAddToParentGroup()
+    {
+        $blockName = 'block_name';
+        $parentGroup = 'parent_group';
+        $this->structureMock->expects($this->once())
+            ->method('addToParentGroup')
+            ->with($this->equalTo($blockName), $this->equalTo($parentGroup))
+            ->will($this->returnSelf());
+        $this->assertSame($this->structureMock, $this->model->addToParentGroup($blockName, $parentGroup));
+    }
+
+    public function testGetGroupChildNames()
+    {
+        $blockName = 'block_name';
+        $groupName = 'group_name';
+        $this->structureMock->expects($this->once())
+            ->method('getGroupChildNames')
+            ->with($this->equalTo($blockName), $this->equalTo($groupName))
+            ->will($this->returnSelf());
+        $this->assertSame($this->structureMock, $this->model->getGroupChildNames($blockName, $groupName));
+    }
+
+    public function testHasElement()
+    {
+        $elementName = 'name';
+        $this->structureMock->expects($this->once())
+            ->method('hasElement')
+            ->with($this->equalTo($elementName))
+            ->will($this->returnValue(true));
+        $this->assertTrue($this->model->hasElement($elementName));
+    }
+
+    public function testGetElementProperty()
+    {
+        $elementName = 'name';
+        $elementAttr = 'attribute';
+        $result = 'result';
+        $this->structureMock->expects($this->once())
+            ->method('getAttribute')
+            ->with($this->equalTo($elementName), $this->equalTo($elementAttr))
+            ->will($this->returnValue($result));
+        $this->assertSame($result, $this->model->getElementProperty($elementName, $elementAttr));
+    }
+
+    /**
+     * @param bool $hasElement
+     * @param string $attribute
+     * @param bool $result
+     * @dataProvider isContainerDataProvider
+     */
+    public function testIsContainer($hasElement, $attribute, $result)
+    {
+        $elementName = 'element_name';
+        $this->structureMock->expects($this->once())
+            ->method('hasElement')
+            ->with($this->equalTo($elementName))
+            ->will($this->returnValue($hasElement));
+        if ($hasElement) {
+            $this->structureMock->expects($this->once())
+                ->method('getAttribute')
+                ->with($this->equalTo($elementName), $this->equalTo('type'))
+                ->will($this->returnValue($attribute));
+        }
+        $this->assertSame($result, $this->model->isContainer($elementName));
+    }
+
+    /**
+     * @return array
+     */
+    public function isContainerDataProvider()
+    {
+        return [
+            [false, '', false],
+            [true, 'container', true],
+            [true, 'block', false],
+            [true, 'something', false],
+        ];
+    }
+
+    /**
+     * @param bool $parentName
+     * @param array $containerConfig
+     * @param bool $result
+     * @dataProvider isManipulationAllowedDataProvider
+     */
+    public function testIsManipulationAllowed($parentName, $containerConfig, $result)
+    {
+        $elementName = 'element_name';
+        $this->structureMock->expects($this->once())
+            ->method('getParentId')
+            ->with($this->equalTo($elementName))
+            ->will($this->returnValue($parentName));
+        if ($parentName) {
+            $this->structureMock->expects($this->once())
+                ->method('hasElement')
+                ->with($this->equalTo($parentName))
+                ->will($this->returnValue($containerConfig['has_element']));
+            if ($containerConfig['has_element']) {
+                $this->structureMock->expects($this->once())
+                    ->method('getAttribute')
+                    ->with($this->equalTo($parentName), $this->equalTo('type'))
+                    ->will($this->returnValue($containerConfig['attribute']));
+            }
+        }
+
+        $this->assertSame($result, $this->model->isManipulationAllowed($elementName));
+    }
+
+    /**
+     * @return array
+     */
+    public function isManipulationAllowedDataProvider()
+    {
+        return [
+            ['parent', ['has_element' => true, 'attribute' => 'container'], true],
+            ['parent', ['has_element' => true, 'attribute' => 'block'], false],
+            [false, [], false],
+        ];
+    }
+
+    /**
+     * @covers \Magento\Framework\View\Layout::setBlock
+     * @covers \Magento\Framework\View\Layout::getAllBlocks
+     * @covers \Magento\Framework\View\Layout::unsetElement
+     */
+    public function testSetGetBlock()
+    {
+        $blockName = 'some_name';
+        $blockMock = $this->getMockBuilder('Magento\Framework\View\Element\AbstractBlock')
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+        $this->assertSame($this->model, $this->model->setBlock($blockName, $blockMock));
+        $this->assertSame([$blockName => $blockMock], $this->model->getAllBlocks());
+        $this->structureMock->expects($this->once())
+            ->method('unsetElement')
+            ->with($this->equalTo($blockName))
+            ->will($this->returnSelf());
+        $this->assertSame($this->model, $this->model->unsetElement($blockName));
+        $this->assertSame([], $this->model->getAllBlocks());
+    }
+
+    public function testRenameElement()
+    {
+        $oldName = 'old_name';
+        $newName = 'new_name';
+        $blockMock = $this->getMockBuilder('Magento\Framework\View\Element\AbstractBlock')
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $this->structureMock->expects($this->once())
+            ->method('renameElement')
+            ->with($this->equalTo($oldName), $this->equalTo($newName))
+            ->will($this->returnSelf());
+        $this->assertSame($this->model, $this->model->setBlock($oldName, $blockMock));
+        $this->assertSame($this->model, $this->model->renameElement($oldName, $newName));
+        $this->assertSame([$newName => $blockMock], $this->model->getAllBlocks());
+    }
+
+    public function testGetParentName()
+    {
+        $childName = 'child_name';
+        $parentId = 'parent_id';
+        $this->structureMock->expects($this->once())
+            ->method('getParentId')
+            ->with($this->equalTo($childName))
+            ->will($this->returnValue($parentId));
+        $this->assertSame($parentId, $this->model->getParentName($childName));
+    }
+
+    public function testGetElementAlias()
+    {
+        $name = 'child_name';
+        $parentId = 'parent_id';
+        $alias = 'alias';
+        $this->structureMock->expects($this->once())
+            ->method('getParentId')
+            ->with($this->equalTo($name))
+            ->will($this->returnValue($parentId));
+        $this->structureMock->expects($this->once())
+            ->method('getChildAlias')
+            ->with($this->equalTo($parentId), $this->equalTo($name))
+            ->will($this->returnValue($alias));
+        $this->assertSame($alias, $this->model->getElementAlias($name));
+    }
+
+    public function testAddRemoveOutputElement()
+    {
+        $this->assertSame($this->model, $this->model->addOutputElement('name'));
+        $this->assertSame($this->model, $this->model->removeOutputElement('name'));
+    }
+
+    public function testGetBlockFactory()
+    {
+        $this->assertSame($this->blockFactoryMock, $this->model->getBlockFactory());
+    }
+
+    public function testIsPrivate()
+    {
+        $this->assertFalse($this->model->isPrivate());
+        $this->assertSame($this->model, $this->model->setIsPrivate(true));
+        $this->assertTrue($this->model->isPrivate());
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Model\Exception
+     * @expectedExceptionMessage Invalid block type
+     */
+    public function testGetBlockSingletonException()
+    {
+        $this->model->getBlockSingleton(false);
+    }
+
+    /**
+     * @param array $type
+     * @param array $blockInstance
+     * @dataProvider getBlockSingletonDataProvider
+     */
+    public function testGetBlockSingleton($type, $blockInstance, $isAbstract)
+    {
+        $blockMock = $this->getMock($blockInstance, [], [], '', false);
+        $this->blockFactoryMock->expects($this->once())
+            ->method('createBlock')
+            ->with($this->equalTo($type))
+            ->will($this->returnValue($blockMock));
+        if ($isAbstract) {
+            $blockMock->expects($this->once())
+                ->method('setLayout')
+                ->with($this->equalTo($this->model))
+                ->will($this->returnSelf());
+        }
+        $this->assertInstanceOf($blockInstance, $this->model->getBlockSingleton($type));
+        // singleton test
+        $this->assertInstanceOf($blockInstance, $this->model->getBlockSingleton($type));
+    }
+
+    /**
+     * @return array
+     */
+    public function getBlockSingletonDataProvider()
+    {
+        return [
+            [
+                'some_type',
+                'Magento\Framework\View\Element\Template',
+                true,
+            ],
+            [
+                'other_type',
+                'stdClass',
+                false,
+            ],
+        ];
+    }
+
+    /**
+     * @param array $rendererData
+     * @param array $getData
+     * @param bool $result
+     * @dataProvider getRendererOptionsDataProvider
+     */
+    public function testAddGetRendererOptions($rendererData, $getData, $result)
+    {
+        $this->assertSame(
+            $this->model,
+            $this->model->addAdjustableRenderer(
+                $rendererData['namespace'],
+                $rendererData['static_type'],
+                $rendererData['dynamic_type'],
+                $rendererData['type'],
+                $rendererData['template'],
+                $rendererData['data']
+            )
+        );
+        $this->assertSame(
+            $result,
+            $this->model->getRendererOptions($getData['namespace'], $getData['static_type'], $getData['dynamic_type'])
         );
+    }
 
-        $this->assertEquals($this->processorMock, $this->_model->getUpdate());
-        $this->assertEquals($this->processorMock, $this->_model->getUpdate());
+    /**
+     * @return array
+     */
+    public function getRendererOptionsDataProvider()
+    {
+        $rendererData = [
+            'namespace' => 'namespace_value',
+            'static_type' => 'static_type_value',
+            'dynamic_type' => 'dynamic_type_value',
+            'type' => 'type_value',
+            'template' => 'template.phtml',
+            'data' => ['some' => 'data']
+        ];
+        return [
+            'wrong namespace' => [
+                $rendererData,
+                [
+                    'namespace' => 'wrong namespace',
+                    'static_type' => 'static_type_value',
+                    'dynamic_type' => 'dynamic_type_value',
+                ],
+                null
+            ],
+            'wrong static type' => [
+                $rendererData,
+                [
+                    'namespace' => 'namespace_value',
+                    'static_type' => 'wrong static type',
+                    'dynamic_type' => 'dynamic_type_value',
+                ],
+                null
+            ],
+            'wrong dynamic type' => [
+                $rendererData,
+                [
+                    'namespace' => 'namespace_value',
+                    'static_type' => 'static_type_value',
+                    'dynamic_type' => 'wrong dynamic type',
+                ],
+                null
+            ],
+            'set and get test' => [
+                $rendererData,
+                [
+                    'namespace' => 'namespace_value',
+                    'static_type' => 'static_type_value',
+                    'dynamic_type' => 'dynamic_type_value',
+                ],
+                [
+                    'type' => 'type_value',
+                    'template' => 'template.phtml',
+                    'data' => ['some' => 'data'],
+                ]
+            ],
+        ];
+    }
+
+    /**
+     * @param string $xmlString
+     * @param bool $result
+     * @dataProvider isCacheableDataProvider
+     */
+    public function testIsCacheable($xmlString, $result)
+    {
+        $xml = simplexml_load_string($xmlString, 'Magento\Framework\View\Layout\Element');
+        $this->assertSame($this->model, $this->model->setXml($xml));
+        $this->assertSame($result, $this->model->isCacheable());
+    }
+
+    /**
+     * @return array
+     */
+    public function isCacheableDataProvider()
+    {
+        return [
+            [
+                '<?xml version="1.0"?><layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
+                . '<block></block></layout>',
+                true
+            ],
+            [
+                '<?xml version="1.0"?><layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
+                . '<block cacheable="false"></block></layout>',
+                false
+            ],
+        ];
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/Render/RenderFactoryTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/Render/RenderFactoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..06b567e5da48eeb5ba2157da0383abce2743b86b
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/Render/RenderFactoryTest.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\View\Render;
+
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+
+class RenderFactoryTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Framework\View\Render\RenderFactory */
+    protected $renderFactory;
+
+    /** @var ObjectManagerHelper */
+    protected $objectManagerHelper;
+
+    /** @var \Magento\Framework\ObjectManager|\PHPUnit_Framework_MockObject_MockObject */
+    protected $objectManagerMock;
+
+    protected function setUp()
+    {
+        $this->objectManagerMock = $this->getMock('Magento\Framework\ObjectManager');
+
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->renderFactory = $this->objectManagerHelper->getObject(
+            'Magento\Framework\View\Render\RenderFactory',
+            [
+                'objectManager' => $this->objectManagerMock
+            ]
+        );
+    }
+
+    public function testGet()
+    {
+        $instance = 'Magento\Framework\View\RenderInterface';
+        $renderMock = $this->getMock($instance, [], [], '', false);
+        $data = 'RenderInterface';
+        $this->objectManagerMock->expects($this->once())
+            ->method('get')
+            ->with($this->equalTo('Magento\Framework\View\Render\RenderInterface'))
+            ->will($this->returnValue($renderMock));
+        $this->assertInstanceOf($instance, $this->renderFactory->get($data));
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage Type "RenderInterface" is not instance on Magento\Framework\View\RenderInterface
+     */
+    public function testGetException()
+    {
+        $this->objectManagerMock->expects($this->once())
+            ->method('get')
+            ->with($this->equalTo('Magento\Framework\View\Render\RenderInterface'))
+            ->will($this->returnValue(new \stdClass()));
+        $this->renderFactory->get('RenderInterface');
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/GiftMessage/Helper/MessageTest.php b/dev/tests/unit/testsuite/Magento/GiftMessage/Helper/MessageTest.php
index 98b778f4551f1cc6731c2eee239d8d23090b5b4f..0bf128cd1169a3d44c43ea06154ac6e82f202d7c 100644
--- a/dev/tests/unit/testsuite/Magento/GiftMessage/Helper/MessageTest.php
+++ b/dev/tests/unit/testsuite/Magento/GiftMessage/Helper/MessageTest.php
@@ -56,7 +56,7 @@ class MessageTest extends \PHPUnit_Framework_TestCase
         $entityMock = $this->getMock('\Magento\Framework\Object', array(), array(), '', false);
         $inlineMock = $this->getMock(
             'Magento\GiftMessage\Block\Message\Inline',
-            array('setId', 'setDontDisplayContainer', 'setEntity', 'setType', 'toHtml'),
+            array('setId', 'setDontDisplayContainer', 'setEntity', 'setCheckoutType', 'toHtml'),
             array(),
             '',
             false
@@ -68,7 +68,7 @@ class MessageTest extends \PHPUnit_Framework_TestCase
         $inlineMock->expects($this->once())->method('setId')->will($this->returnSelf());
         $inlineMock->expects($this->once())->method('setDontDisplayContainer')->will($this->returnSelf());
         $inlineMock->expects($this->once())->method('setEntity')->with($entityMock)->will($this->returnSelf());
-        $inlineMock->expects($this->once())->method('setType')->will($this->returnSelf());
+        $inlineMock->expects($this->once())->method('setCheckoutType')->will($this->returnSelf());
         $inlineMock->expects($this->once())->method('toHtml')->will($this->returnValue($expectedHtml));
 
         $this->assertEquals($expectedHtml, $this->helper->getInline('onepage_checkout', $entityMock));
diff --git a/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/Attribute/ContentTest.php b/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/Attribute/ContentTest.php
index ff0cf157981757382116ac3413856972f7323a12..349e5339af78e90c42953af1876449fceeae6657 100644
--- a/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/Attribute/ContentTest.php
+++ b/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/Attribute/ContentTest.php
@@ -76,14 +76,14 @@ class ContentTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnValue($attribute));
 
 
-        $gsData = $this->getMock(
+        $googleShoppingHelper = $this->getMock(
             '\Magento\GoogleShopping\Helper\Data',
             array('cleanAtomAttribute'),
             array(),
             '',
             false
         );
-        $gsData->expects($this->once())
+        $googleShoppingHelper->expects($this->once())
             ->method('cleanAtomAttribute')
             ->with($mapValue)
             ->will($this->returnValue($mapValue));
@@ -91,7 +91,7 @@ class ContentTest extends \PHPUnit_Framework_TestCase
         $model = (new \Magento\TestFramework\Helper\ObjectManager($this))
             ->getObject(
                 '\Magento\GoogleShopping\Model\Attribute\Content',
-                array('gsProduct' => $productHelper, 'gsData' => $gsData)
+                array('gsProduct' => $productHelper, 'googleShoppingHelper' => $googleShoppingHelper)
             );
 
         $service = $this->getMock('Zend_Gdata_App', array('newContent', 'setText'), array(), '', false);
diff --git a/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/Attribute/TaxTest.php b/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/Attribute/TaxTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..18854daef3e85bea5eb115b8aa416a115105fce1
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/Attribute/TaxTest.php
@@ -0,0 +1,337 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\GoogleShopping\Model\Attribute;
+
+/**
+ * Class TaxTest
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class TaxTest extends \PHPUnit_Framework_TestCase
+{
+
+    /**
+     * @var \Magento\Tax\Helper\Data | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $mockTaxHelper;
+
+    /**
+     * @var \Magento\Tax\Service\V1\TaxRuleService | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $mockTaxRuleService;
+
+    /**
+     * @var \Magento\GoogleShopping\Model\Config | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $mockConfig;
+
+    /**
+     * @var \Magento\GoogleShopping\Model\Resource\Attribute | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $mockResource;
+
+    /**
+     * @var \Magento\Customer\Service\V1\CustomerGroupServiceInterface | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $mockGroupService;
+
+    /**
+     * @var \Magento\Tax\Service\V1\Data\QuoteDetailsBuilder | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $mockQuoteDetailsBuilder;
+
+    /**
+     * @var \Magento\Tax\Service\V1\TaxCalculationService | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $mockTaxCalculationService;
+
+    /**
+     * @var \Magento\Directory\Model\RegionFactory | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $mockRegionFactory;
+
+    /**
+     * @var  \Magento\GoogleShopping\Model\Attribute\Tax
+     */
+    protected $model;
+
+    public function setUp()
+    {
+        $this->mockTaxHelper = $this->getMockBuilder('\Magento\Tax\Helper\Data')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->mockTaxRuleService = $this->getMockBuilder('Magento\Tax\Service\V1\TaxRuleService')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->mockConfig = $this->getMockBuilder('\Magento\GoogleShopping\Model\Config')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->mockGroupService = $this->getMockBuilder('\Magento\Customer\Service\V1\CustomerGroupServiceInterface')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->mockQuoteDetailsBuilder = $this->getMockBuilder('\Magento\Tax\Service\V1\Data\QuoteDetailsBuilder')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->mockTaxCalculationService = $this->getMockBuilder('\Magento\Tax\Service\V1\TaxCalculationService')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->mockRegionFactory = $this->getMockBuilder('\Magento\Directory\Model\RegionFactory')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $arguments = [
+            'taxData' => $this->mockTaxHelper,
+            'taxRuleService' => $this->mockTaxRuleService,
+            'groupServiceInterface' => $this->mockGroupService,
+            'config' => $this->mockConfig,
+            'quoteDetailsBuilder' => $this->mockQuoteDetailsBuilder,
+            'taxCalculationService' => $this->mockTaxCalculationService,
+            'regionFactory' => $this->mockRegionFactory
+        ];
+        $this->model = $objectManager->getObject('Magento\GoogleShopping\Model\Attribute\Tax', $arguments);
+    }
+
+    public function testGetDefaultCustomerTaxClass()
+    {
+        $taxClassId = 'tax_class_id';
+        $store = 'store';
+        $this->setUpGetDefaultCustomerTaxClass($taxClassId, $store);
+
+        $reflectionObject = new \ReflectionObject($this->model);
+        $reflectionMethod = $reflectionObject->getMethod('_getDefaultCustomerTaxClassId');
+        $reflectionMethod->setAccessible(true);
+        $this->assertSame($taxClassId, $reflectionMethod->invokeArgs($this->model, [$store]));
+    }
+
+    public function testGetRegionsByRegionId()
+    {
+        $regionId = 1;
+        $postalCode = '*';
+        $regionCode = '90210';
+        $this->setUpGetRegionsByRegionId($regionId, $regionCode);
+
+        $reflectionObject = new \ReflectionObject($this->model);
+        $reflectionMethod = $reflectionObject->getMethod('_getRegionsByRegionId');
+        $reflectionMethod->setAccessible(true);
+        $this->assertSame([$regionCode], $reflectionMethod->invokeArgs($this->model, [$regionId, $postalCode]));
+    }
+
+    public function testConvertAttribute()
+    {
+        $productStoreId = 'product_store_id';
+        $sku = 'sku';
+        $price = 'price';
+        $name = 'name';
+        $productTaxClassId = 'product_tax_class_id';
+        $customerTaxClassId = 'tax_class_id';
+        $postCode = '90210';
+        $this->setUpGetDefaultCustomerTaxClass($customerTaxClassId, $productStoreId);
+        $this->setUpGetRegionsByRegionId($postCode, '*');
+        $this->mockTaxHelper->expects($this->any())->method('getConfig')->will($this->returnSelf());
+        $this->mockTaxHelper->expects($this->any())->method('priceIncludesTax')->will($this->returnValue(false));
+        $mockTaxRate = $this->getMockBuilder('Magento\Tax\Service\V1\Data\TaxRate')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $rates = [$mockTaxRate];
+        $this->mockTaxRuleService->expects($this->once())->method('getRatesByCustomerAndProductTaxClassId')->with(
+            $customerTaxClassId,
+            $productTaxClassId
+        )->will($this->returnValue($rates));
+        $targetCountry = 'target_country';
+        $this->mockConfig->expects($this->once())->method('getTargetCountry')->with($productStoreId)->will(
+            $this->returnValue($targetCountry)
+        );
+        $mockTaxRate->expects($this->once())->method('getCountryId')->will($this->returnValue($targetCountry));
+        $mockTaxRate->expects($this->once())->method('getPostcode')->will($this->returnValue($postCode));
+        $mockTaxRate->expects($this->any())->method('getRegionId')->will($this->returnValue($postCode));
+
+        $this->mockQuoteDetailsBuilder->expects($this->once())->method('populateWithArray')
+            ->with(
+                [
+                    'billing_address'       => [
+                        'country_id'  => $targetCountry,
+                        'region'      => ['region_id' => $postCode],
+                        'postcode'    => $postCode
+                    ],
+                    'shipping_address'      => [
+                        'country_id'  => $targetCountry,
+                        'region'      => ['region_id' => $postCode],
+                        'postcode'    => $postCode
+                    ],
+                    'customer_tax_class_key' => [
+                        'type' => 'id',
+                        'value' => $customerTaxClassId,
+                    ],
+                    'items'                 => [
+                        [
+                            'code'              => $sku,
+                            'type'              => 'product',
+                            'tax_class_key'      => [
+                                'type' => 'id',
+                                'value' => $productTaxClassId,
+                            ],
+                            'unit_price'        => $price,
+                            'quantity'          => 1,
+                            'tax_included'      => 1,
+                            'short_description' => $name
+                        ]
+                    ]
+                ]
+            )
+            ->will($this->returnSelf());
+        /** @var \Magento\Tax\Service\V1\Data\QuoteDetails
+         * | \PHPUnit_Framework_MockObject_MockObject $quoteDetailsObject */
+        $quoteDetailsObject = $this->getMockBuilder('Magento\Tax\Service\V1\Data\QuoteDetails')
+            ->disableOriginalConstructor()->getMock();
+        $this->mockQuoteDetailsBuilder->expects($this->once())->method('create')->will(
+            $this->returnValue($quoteDetailsObject)
+        );
+        $taxDetailsObject = $this->getMockBuilder('\Magento\Tax\Service\V1\Data\TaxDetails')
+            ->disableOriginalConstructor()->getMock();
+        $this->mockTaxCalculationService->expects($this->once())->method('calculateTax')->with(
+            $quoteDetailsObject,
+            $productStoreId
+        )->will($this->returnValue($taxDetailsObject));
+        $taxAmount = 777;
+        $subTotal = 555;
+        $taxDetailsObject->expects($this->once())->method('getTaxAmount')->will($this->returnValue($taxAmount));
+        $taxDetailsObject->expects($this->once())->method('getSubtotal')->will($this->returnValue($subTotal));
+        $taxRate = ($taxAmount / $subTotal) * 100;
+        // mock product
+        $mockProduct = $this->getMockProduct($productStoreId, $productTaxClassId, $sku, $price, $name);
+        $mockEntry = $this->getMockEntry();
+        $mockEntry->expects($this->once())
+            ->method('addTax')
+            ->with(
+                [
+                    'tax_rate'    => $taxRate,
+                    'tax_country' => $targetCountry,
+                    'tax_region'  => $postCode,
+                ]
+            );
+        $this->assertSame($mockEntry, $this->model->convertAttribute($mockProduct, $mockEntry));
+    }
+
+    private function setUpGetDefaultCustomerTaxClass($taxClassId, $store)
+    {
+        $mockGroup = $this->getMockBuilder('\Magento\Customer\Service\V1\Data\CustomerGroup')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->mockGroupService->expects($this->once())
+            ->method('getDefaultGroup')
+            ->with($store)
+            ->will($this->returnValue($mockGroup));
+
+        $mockGroup->expects($this->once())
+            ->method('getTaxClassId')
+            ->will($this->returnValue($taxClassId));
+    }
+
+    private function setUpGetRegionsByRegionId($regionId, $code)
+    {
+        $mockRegion = $this->getMockBuilder('\Magento\Directory\Model\Region')
+            ->disableOriginalConstructor()
+            ->setMethods(['getCode', 'load', '__wakeup'])
+            ->getMock();
+
+        $mockRegion->expects($this->once())
+            ->method('load')
+            ->with($regionId)
+            ->will($this->returnSelf());
+
+        $mockRegion->expects($this->once())
+            ->method('getCode')
+            ->will($this->returnValue($code));
+
+        $this->mockRegionFactory->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($mockRegion));
+    }
+
+    /**
+     * Get a mock product object.
+     *
+     * @param $productStoreId
+     * @param $productTaxClassId
+     * @param $sku
+     * @param $price
+     * @param $name
+     * @return \Magento\Catalog\Model\Product | \PHPUnit_Framework_MockObject_MockObject
+     */
+    private function getMockProduct($productStoreId, $productTaxClassId, $sku, $price, $name)
+    {
+        $mockProduct = $this->getMockBuilder('\Magento\Catalog\Model\Product')
+            ->setMethods(
+                [
+                    'getTaxClassId',
+                    '__wakeup',
+                    'getStoreId',
+                    'getPriceInfo',
+                    'getAdjustments',
+                    'getSku',
+                    'getPrice',
+                    'getName'
+                ]
+            )
+            ->disableOriginalConstructor()
+            ->getMock();
+        $mockProduct->expects($this->once())
+            ->method('getPriceInfo')
+            ->will($this->returnSelf());
+        $mockProduct->expects($this->once())
+            ->method('getAdjustments')
+            ->will($this->returnValue(['tax' => 'something']));
+        $mockProduct->expects($this->any())
+            ->method('getStoreId')
+            ->will($this->returnValue($productStoreId));
+        $mockProduct->expects($this->any())
+            ->method('getTaxClassId')
+            ->will($this->returnValue($productTaxClassId));
+        $mockProduct->expects($this->once())
+            ->method('getSku')
+            ->will($this->returnValue($sku));
+        $mockProduct->expects($this->once())
+            ->method('getPrice')
+            ->will($this->returnValue($price));
+        $mockProduct->expects($this->once())
+            ->method('getName')
+            ->will($this->returnValue($name));
+        return $mockProduct;
+    }
+
+    /**
+     * Get a mock entry object.
+     *
+     * @return \Magento\Framework\Gdata\Gshopping\Entry | \PHPUnit_Framework_MockObject_MockObject
+     */
+    private function getMockEntry()
+    {
+        $mockEntry = $this->getMockBuilder('\Magento\Framework\Gdata\Gshopping\Entry')
+            ->disableOriginalConstructor()
+            ->getMock();
+        return $mockEntry;
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Payment/Helper/DataTest.php b/dev/tests/unit/testsuite/Magento/Payment/Helper/DataTest.php
index 666a2f5a89ec9529bf246ba68c5aeed032f7c5b8..c1ac9481ec47b8fb0c63d9ad2d51bc65359b65e6 100644
--- a/dev/tests/unit/testsuite/Magento/Payment/Helper/DataTest.php
+++ b/dev/tests/unit/testsuite/Magento/Payment/Helper/DataTest.php
@@ -32,6 +32,9 @@ class DataTest extends \PHPUnit_Framework_TestCase
     /**  @var \PHPUnit_Framework_MockObject_MockObject */
     protected $_scopeConfig;
 
+    /**  @var \PHPUnit_Framework_MockObject_MockObject */
+    protected $_initialConfig;
+
     /**  @var \PHPUnit_Framework_MockObject_MockObject */
     protected $_methodFactory;
 
@@ -43,7 +46,7 @@ class DataTest extends \PHPUnit_Framework_TestCase
         $this->_methodFactory = $this->getMock('Magento\Payment\Model\Method\Factory', [], [], '', false);
         $appEmulation         = $this->getMock('Magento\Core\Model\App\Emulation', [], [], '', false);
         $paymentConfig        = $this->getMock('Magento\Payment\Model\Config', [], [], '', false);
-        $initialConfig        = $this->getMock('Magento\Framework\App\Config\Initial', [], [], '', false);
+        $this->_initialConfig = $this->getMock('Magento\Framework\App\Config\Initial', [], [], '', false);
 
         $this->_helper = new \Magento\Payment\Helper\Data(
             $context,
@@ -52,7 +55,7 @@ class DataTest extends \PHPUnit_Framework_TestCase
             $this->_methodFactory,
             $appEmulation,
             $paymentConfig,
-            $initialConfig
+            $this->_initialConfig
         );
     }
 
@@ -88,6 +91,68 @@ class DataTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals($methodInstance, $this->_helper->getMethodInstance($code));
     }
 
+    /**
+     * @param $method1 array
+     * @param $method2 array
+     *
+     * @dataProvider getSortMethodsDataProvider
+     */
+    public function testSortMethods($method1, $method2)
+    {
+        $this->_initialConfig->expects($this->once())
+            ->method('getData')
+            ->will($this->returnValue(
+                array(\Magento\Payment\Helper\Data::XML_PATH_PAYMENT_METHODS => array(
+                    'method1' => $method1,
+                    'method2 '=> $method2
+                ))
+            ));
+
+        $this->_scopeConfig->expects($this->any())
+            ->method('getValue')
+            ->will($this->returnValue('Magento\Payment\Model\Method\AbstractMethod'));
+
+        $methodInstanceMock1 = $this->getMock(
+            'Magento\Framework\Object',
+            array('isAvailable','getConfigData'),
+            array(),
+            '',
+            false
+        );
+        $methodInstanceMock1->expects($this->any())
+            ->method('isAvailable')
+            ->will($this->returnValue(true));
+        $methodInstanceMock1->expects($this->any())
+            ->method('getConfigData')
+            ->will($this->returnValue($method1['sort_order']));
+
+        $methodInstanceMock2 = $this->getMock(
+            'Magento\Framework\Object',
+            array('isAvailable','getConfigData'),
+            array(),
+            '',
+            false
+        );
+        $methodInstanceMock2->expects($this->any())
+            ->method('isAvailable')
+            ->will($this->returnValue(true));
+        $methodInstanceMock2->expects($this->any())
+            ->method('getConfigData')
+            ->will($this->returnValue($method2['sort_order']));
+
+        $this->_methodFactory->expects($this->at(0))
+            ->method('create')
+            ->will($this->returnValue($methodInstanceMock1));
+
+        $this->_methodFactory->expects($this->at(1))
+            ->method('create')
+            ->will($this->returnValue($methodInstanceMock2));
+
+        $sortedMethods = $this->_helper->getStoreMethods();
+        $this->assertTrue(array_shift($sortedMethods)->getSortOrder() < array_shift($sortedMethods)->getSortOrder());
+    }
+
+
     public function getMethodInstanceDataProvider()
     {
         return array(
@@ -95,4 +160,18 @@ class DataTest extends \PHPUnit_Framework_TestCase
             ['method_code', false, false]
         );
     }
+
+    public function getSortMethodsDataProvider()
+    {
+        return array(
+            array(
+                array('sort_order' => 0),
+                array('sort_order' => 1)
+            ),
+            array(
+                array('sort_order' => 2),
+                array('sort_order' => 1),
+            )
+        );
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Payment/Model/CartTest.php b/dev/tests/unit/testsuite/Magento/Payment/Model/CartTest.php
index 02d0d87fbbdfc5da3db80d3e595df82e974a4d5c..75b9ffc41abd813a7587709ba695214b3c9ed6c8 100644
--- a/dev/tests/unit/testsuite/Magento/Payment/Model/CartTest.php
+++ b/dev/tests/unit/testsuite/Magento/Payment/Model/CartTest.php
@@ -294,11 +294,22 @@ class CartTest extends \PHPUnit_Framework_TestCase
      */
     protected function _getSalesModelItems()
     {
+        $product = new \Magento\Framework\Object(['id' => '1']);
         return array(
-            new \Magento\Framework\Object(array('name' => 'name 1', 'qty' => 1, 'price' => 0.1)),
-            new \Magento\Framework\Object(array('name' => 'name 2', 'qty' => 2, 'price' => 1.2)),
             new \Magento\Framework\Object(
-                array('parent_item' => 'parent item 3', 'name' => 'name 3', 'qty' => 3, 'price' => 2.3)
+                ['name' => 'name 1', 'qty' => 1, 'price' => 0.1, 'original_item' => $product]
+            ),
+            new \Magento\Framework\Object(
+                ['name' => 'name 2', 'qty' => 2, 'price' => 1.2, 'original_item' => $product]
+            ),
+            new \Magento\Framework\Object(
+                [
+                    'parent_item' => 'parent item 3',
+                    'name' => 'name 3',
+                    'qty' => 3,
+                    'price' => 2.3,
+                    'original_item' => $product
+                ]
             )
         );
     }
@@ -317,7 +328,12 @@ class CartTest extends \PHPUnit_Framework_TestCase
                 continue;
             }
             $result[] = new \Magento\Framework\Object(
-                array('name' => $item->getName(), 'qty' => $item->getQty(), 'amount' => $item->getPrice())
+                array(
+                    'name' => $item->getName(),
+                    'qty' => $item->getQty(),
+                    'amount' => $item->getPrice(),
+                    'id' => $item->getOriginalItem()->getId()
+                )
             );
         }
         return $result;
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Controller/Ipn/IndexTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Controller/Ipn/IndexTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9e93e78829df963c995099518043fb3ec8c0712b
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Controller/Ipn/IndexTest.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Controller\Ipn;
+
+class IndexTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var Index */
+    protected $model;
+
+    /** @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject */
+    protected $logger;
+
+    /** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $request;
+
+    /** @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $response;
+
+    protected function setUp()
+    {
+        $this->logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->request = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false);
+        $this->response = $this->getMock('Magento\Framework\App\Response\Http', [], [], '', false);
+
+        $objectManagerHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->model = $objectManagerHelper->getObject(
+            'Magento\Paypal\Controller\Ipn\Index',
+            [
+                'logger' => $this->logger,
+                'request' => $this->request,
+                'response' => $this->response,
+            ]
+        );
+    }
+
+    public function testIndexActionException()
+    {
+        $this->request->expects($this->once())->method('isPost')->will($this->returnValue(true));
+        $exception = new \Exception();
+        $this->request->expects($this->once())->method('getPost')->will($this->throwException($exception));
+        $this->logger->expects($this->once())->method('logException')->with($this->identicalTo($exception));
+        $this->response->expects($this->once())->method('setHttpResponseCode')->with(500);
+        $this->model->execute();
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/ValidatorTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/ValidatorTest.php
index 867c79fe172b2aa2d174b9082086320320964148..251ee0a8c2a650cb2ecf403bf1bc085bbbbf989d 100644
--- a/dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/ValidatorTest.php
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/ValidatorTest.php
@@ -106,7 +106,17 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
      */
     public function testIsPriceOrSetAvailable($isInCatalog, $productPrice, $isProductSet, $expected)
     {
-        $currentProduct = new \Magento\Framework\Object(['final_price' => $productPrice, 'type_id' => 'simple']);
+        $currentProduct = $this->getMockBuilder('Magento\Catalog\Model\Product')->disableOriginalConstructor()
+            ->setMethods(['__wakeup', 'getFinalPrice', 'getTypeId', 'getTypeInstance'])
+            ->getMock();
+        $typeInstance = $this->getMockBuilder('Magento\Catalog\Model\Product\Type\AbstractType')
+            ->disableOriginalConstructor()
+            ->setMethods([])
+            ->getMock();
+        $currentProduct->expects($this->any())->method('getFinalPrice')->will($this->returnValue($productPrice));
+        $currentProduct->expects($this->any())->method('getTypeId')->will($this->returnValue('simple'));
+        $currentProduct->expects($this->any())->method('getTypeInstance')->will($this->returnValue($typeInstance));
+
         $this->_registry->expects($this->any())
             ->method('registry')
             ->with($this->equalTo('current_product'))
@@ -116,6 +126,11 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
             ->method('isProductSet')
             ->will($this->returnValue($isProductSet));
 
+        $typeInstance->expects($this->any())
+            ->method('canConfigure')
+            ->with($currentProduct)
+            ->will($this->returnValue(false));
+
         $this->assertEquals($expected, $this->helper->isPriceOrSetAvailable($isInCatalog));
     }
 
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/Api/NvpTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/Api/NvpTest.php
index 4bcee55b0f43706757e4876d584551f78fca9be9..0d195b7957ca26364fd289ee27c4058eaef1dab0 100644
--- a/dev/tests/unit/testsuite/Magento/Paypal/Model/Api/NvpTest.php
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Model/Api/NvpTest.php
@@ -155,6 +155,21 @@ class NvpTest extends \PHPUnit_Framework_TestCase
                 'PayPal gateway has rejected request. Long Message (#10417: Message).',
                 10417
             ],
+            [
+                "\r\n" . 'ACK[7]=Failure&L_ERRORCODE0[5]=10417'
+                    . '&L_SHORTMESSAGE0[8]=Message.&L_LONGMESSAGE0[15]=Long%20Message.',
+                [10417, 10422],
+                'Magento\Paypal\Model\Api\ProcessableException',
+                'PayPal gateway has rejected request. Long Message (#10417: Message).',
+                10417
+            ],
+            [
+                "\r\n" . 'ACK[7]=Failure&L_ERRORCODE0[5]=10417&L_SHORTMESSAGE0[8]=Message.',
+                [10417, 10422],
+                'Magento\Paypal\Model\Api\ProcessableException',
+                'PayPal gateway has rejected request. #10417: Message.',
+                10417
+            ],
         ];
     }
 
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/CartTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/CartTest.php
index 3d812332426c72199a09718b96fadc6efcb783a3..81aea8dee63376cb7451124504387df24bc57116 100644
--- a/dev/tests/unit/testsuite/Magento/Paypal/Model/CartTest.php
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Model/CartTest.php
@@ -379,4 +379,12 @@ class CartTest extends \PHPUnit_Framework_TestCase
         );
         return $totals;
     }
+
+    public function testHasNegativeItemAmount()
+    {
+        $this->_model->addCustomItem('item1', 1, 2.1);
+        $this->assertFalse($this->_model->hasNegativeItemAmount());
+        $this->_model->addCustomItem('item1', 1, -1.3);
+        $this->assertTrue($this->_model->hasNegativeItemAmount());
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/Hostedpro/RequestTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/Hostedpro/RequestTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3e962f68a511d44c187dd619f639db203451aad9
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Model/Hostedpro/RequestTest.php
@@ -0,0 +1,113 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Paypal\Model\Hostedpro;
+
+class RequestTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Paypal\Model\Hostedpro\Request
+     */
+    protected $_model;
+
+    protected function setUp()
+    {
+        $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->_model = $helper->getObject(
+            'Magento\Paypal\Model\Hostedpro\Request'
+        );
+    }
+
+    /**
+     * @dataProvider addressesDataProvider
+     */
+    public function testSetOrderAddresses($billing, $shipping, $billingState, $state)
+    {
+        $payment = $this->getMock('Magento\Sales\Model\Order\Payment', ['__wakeup'], [], '', false);
+        $order = $this->getMock(
+            'Magento\Sales\Model\Order',
+            ['getPayment', '__wakeup', 'getBillingAddress', 'getShippingAddress'],
+            [],
+            '',
+            false
+        );
+        $order->expects($this->any())
+            ->method('getPayment')
+            ->will($this->returnValue($payment));
+        $order->expects($this->any())
+            ->method('getBillingAddress')
+            ->will($this->returnValue($billing));
+        $order->expects($this->any())
+            ->method('getShippingAddress')
+            ->will($this->returnValue($shipping));
+        $this->_model->setOrder($order);
+        $this->assertEquals($billingState, $this->_model->getData('billing_state'));
+        $this->assertEquals($state, $this->_model->getData('state'));
+    }
+
+    /**
+     * @return array
+     */
+    public function addressesDataProvider()
+    {
+        $billing = new \Magento\Framework\Object([
+            'firstname' => 'Firstname',
+            'lastname' => 'Lastname',
+            'city' => 'City',
+            'region_code' => 'CA',
+            'postcode' => '12346',
+            'country' => 'United States',
+            'Street' => '1 Ln Ave'
+        ]);
+        $shipping = new \Magento\Framework\Object([
+            'firstname' => 'ShipFirstname',
+            'lastname' => 'ShipLastname',
+            'city' => 'ShipCity',
+            'region' => 'olala',
+            'postcode' => '12346',
+            'country' => 'United States',
+            'Street' => '1 Ln Ave'
+        ]);
+        $billing2 = new \Magento\Framework\Object([
+            'firstname' => 'Firstname',
+            'lastname' => 'Lastname',
+            'city' => 'City',
+            'region_code' => 'muuuu',
+            'postcode' => '12346',
+            'country' => 'United States',
+            'Street' => '1 Ln Ave'
+        ]);
+        $shipping2 = new \Magento\Framework\Object([
+            'firstname' => 'ShipFirstname',
+            'lastname' => 'ShipLastname',
+            'city' => 'ShipCity',
+            'postcode' => '12346',
+            'country' => 'United States',
+            'Street' => '1 Ln Ave'
+        ]);
+        return [
+            [$billing, $shipping, 'CA', 'olala'],
+            [$billing2, $shipping2, 'muuuu', 'ShipCity']
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/IpnTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/IpnTest.php
index 3945c6e4e91f5391d0adfc76b8ddf6de1385e8d5..7ad537f55d52709ba2ffd28c85f16fad78bf016e 100644
--- a/dev/tests/unit/testsuite/Magento/Paypal/Model/IpnTest.php
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Model/IpnTest.php
@@ -27,6 +27,8 @@
  */
 namespace Magento\Paypal\Model;
 
+use \Magento\Sales\Model\Order;
+
 class IpnTest extends \PHPUnit_Framework_TestCase
 {
     /**
@@ -44,6 +46,16 @@ class IpnTest extends \PHPUnit_Framework_TestCase
      */
     protected $_paypalInfo;
 
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $configFactory;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $curlFactory;
+
     protected function setUp()
     {
         $methods = [
@@ -57,7 +69,8 @@ class IpnTest extends \PHPUnit_Framework_TestCase
             'registerPaymentReviewAction',
             'getAdditionalInformation',
             'getEmailSent',
-            'save'
+            'save',
+            'getState'
         ];
         $this->_orderMock = $this->getMock('Magento\Sales\Model\OrderFactory', $methods, [], '', false);
         $this->_orderMock->expects($this->any())->method('create')->will($this->returnSelf());
@@ -67,30 +80,31 @@ class IpnTest extends \PHPUnit_Framework_TestCase
         $this->_orderMock->expects($this->any())->method('getStoreId')->will($this->returnSelf());
         $this->_orderMock->expects($this->any())->method('getEmailSent')->will($this->returnValue(true));
 
-        $configFactory = $this->getMock(
+        $this->configFactory = $this->getMock(
             'Magento\Paypal\Model\ConfigFactory',
             ['create', 'isMethodActive', 'isMethodAvailable', 'getConfigValue', 'getPaypalUrl'],
             [],
             '',
             false
         );
-        $configFactory->expects($this->any())->method('create')->will($this->returnSelf());
-        $configFactory->expects($this->any())->method('isMethodActive')->will($this->returnValue(true));
-        $configFactory->expects($this->any())->method('isMethodAvailable')->will($this->returnValue(true));
-        $configFactory->expects($this->any())->method('getConfigValue')->will($this->returnValue(null));
-        $configFactory->expects($this->any())->method('getPaypalUrl')->will($this->returnValue('http://paypal_url'));
+        $this->configFactory->expects($this->any())->method('create')->will($this->returnSelf());
+        $this->configFactory->expects($this->any())->method('isMethodActive')->will($this->returnValue(true));
+        $this->configFactory->expects($this->any())->method('isMethodAvailable')->will($this->returnValue(true));
+        $this->configFactory->expects($this->any())->method('getConfigValue')->will($this->returnValue(null));
+        $this->configFactory->expects($this->any())->method('getPaypalUrl')
+            ->will($this->returnValue('http://paypal_url'));
 
-        $curlFactory = $this->getMock(
+        $this->curlFactory = $this->getMock(
             'Magento\Framework\HTTP\Adapter\CurlFactory',
             ['create', 'setConfig', 'write', 'read'],
             [],
             '',
             false
         );
-        $curlFactory->expects($this->any())->method('create')->will($this->returnSelf());
-        $curlFactory->expects($this->any())->method('setConfig')->will($this->returnSelf());
-        $curlFactory->expects($this->any())->method('write')->will($this->returnSelf());
-        $curlFactory->expects($this->any())->method('read')->will($this->returnValue(
+        $this->curlFactory->expects($this->any())->method('create')->will($this->returnSelf());
+        $this->curlFactory->expects($this->any())->method('setConfig')->will($this->returnSelf());
+        $this->curlFactory->expects($this->any())->method('write')->will($this->returnSelf());
+        $this->curlFactory->expects($this->any())->method('read')->will($this->returnValue(
             '
                 VERIFIED'
         ));
@@ -105,9 +119,9 @@ class IpnTest extends \PHPUnit_Framework_TestCase
         $objectHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
         $this->_ipn = $objectHelper->getObject('Magento\Paypal\Model\Ipn',
             [
-                'configFactory' => $configFactory,
+                'configFactory' => $this->configFactory,
                 'logAdapterFactory' => $this->getMock('Magento\Framework\Logger\AdapterFactory', [], [], '', false),
-                'curlFactory' => $curlFactory,
+                'curlFactory' => $this->curlFactory,
                 'orderFactory' => $this->_orderMock,
                 'paypalInfo' => $this->_paypalInfo,
                 'data' => ['payment_status' => 'Pending', 'pending_reason' => 'authorization']
@@ -150,4 +164,53 @@ class IpnTest extends \PHPUnit_Framework_TestCase
         )->will($this->returnSelf());
         $this->_ipn->processIpnRequest();
     }
+
+    public function testPaymentReviewRegisterPaymentFraud()
+    {
+        $paymentMock = $this->getMock(
+            '\Magento\Sales\Model\Order\Payment',
+            ['getAdditionalInformation', '__wakeup', 'registerCaptureNotification'],
+            [],
+            '',
+            false
+        );
+        $paymentMock->expects($this->any())
+            ->method('getAdditionalInformation')
+            ->will($this->returnValue([]));
+        $paymentMock->expects($this->any())
+            ->method('registerCaptureNotification')
+            ->will($this->returnValue(true));
+        $this->_orderMock->expects($this->any())->method('getPayment')->will($this->returnValue($paymentMock));
+        $this->_orderMock->expects($this->any())->method('canFetchPaymentReviewUpdate')->will($this->returnValue(true));
+        $this->_orderMock->expects($this->once())->method('getState')->will(
+            $this->returnValue(Order::STATE_PENDING_PAYMENT)
+        );
+        $this->_paypalInfo->expects($this->once())
+            ->method('importToPayment')
+            ->with(
+                [
+                    'payment_status' => 'pending',
+                    'pending_reason' => 'fraud',
+                    'collected_fraud_filters' => ['Maximum Transaction Amount']
+                ],
+                $paymentMock
+            );
+        $objectHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->_ipn = $objectHelper->getObject('Magento\Paypal\Model\Ipn',
+            [
+                'configFactory' => $this->configFactory,
+                'logAdapterFactory' => $this->getMock('Magento\Framework\Logger\AdapterFactory', [], [], '', false),
+                'curlFactory' => $this->curlFactory,
+                'orderFactory' => $this->_orderMock,
+                'paypalInfo' => $this->_paypalInfo,
+                'data' => [
+                    'payment_status' => 'Pending',
+                    'pending_reason' => 'fraud',
+                    'fraud_management_pending_filters_1' => 'Maximum Transaction Amount'
+                ]
+            ]
+        );
+        $this->_ipn->processIpnRequest();
+        $this->assertEquals('IPN "Pending"', $paymentMock->getPreparedMessage());
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/Method/Checks/SpecificationPluginTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/Method/Checks/SpecificationPluginTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b62c97db433301d8af37db353fb2e0071c179462
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Model/Method/Checks/SpecificationPluginTest.php
@@ -0,0 +1,172 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Model\Method\Checks;
+
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+use Magento\Payment\Model\Checks\PaymentMethodChecksInterface;
+use Magento\Sales\Model\Quote;
+use Magento\Paypal\Model\Billing\AgreementFactory;
+
+class SpecificationPluginTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var SpecificationPlugin */
+    protected $model;
+
+    /** @var AgreementFactory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $agreementFactory;
+
+    protected function setUp()
+    {
+        $this->agreementFactory = $this->getMock('Magento\Paypal\Model\Billing\AgreementFactory', ['create']);
+
+        $objectManagerHelper = new ObjectManagerHelper($this);
+        $this->model = $objectManagerHelper->getObject(
+            'Magento\Paypal\Model\Method\Checks\SpecificationPlugin',
+            [
+                'agreementFactory' => $this->agreementFactory
+            ]
+        );
+    }
+
+    public function testAroundIsApplicableNotOriginallyApplicable()
+    {
+        $paymentMethod = $this->getPaymentMethod('any');
+        $quote = $this->getQuote('any');
+        $proceed = $this->getProceedClosure(false, $paymentMethod, $quote);
+        $this->assertFalse($this->callAroundIsApplicable($proceed, $paymentMethod, $quote));
+    }
+
+    public function testAroundIsApplicableNotAgreement()
+    {
+        $paymentMethod = $this->getPaymentMethod('not_agreement');
+        $quote = $this->getQuote('any');
+        $proceed = $this->getProceedClosure(true, $paymentMethod, $quote);
+        $this->assertTrue($this->callAroundIsApplicable($proceed, $paymentMethod, $quote));
+    }
+
+    public function testAroundIsApplicableNoCustomerId()
+    {
+        $paymentMethod = $this->getPaymentMethod('paypal_billing_agreement');
+        $quote = $this->getQuote(null);
+        $proceed = $this->getProceedClosure(true, $paymentMethod, $quote);
+        $this->assertTrue($this->callAroundIsApplicable($proceed, $paymentMethod, $quote));
+    }
+
+    /**
+     * @param int $count
+     * @dataProvider aroundIsApplicableDataProvider
+     */
+    public function testAroundIsApplicable($count)
+    {
+        $paymentMethod = $this->getPaymentMethod('paypal_billing_agreement');
+        $quote = $this->getQuote(1);
+        $proceed = $this->getProceedClosure(true, $paymentMethod, $quote);
+        $agreementCollection = $this->getMock(
+            'Magento\Paypal\Model\Resource\Billing\Agreement\Collection',
+            [],
+            [],
+            '',
+            false
+        );
+        $agreementCollection->expects($this->once())
+            ->method('count')
+            ->will($this->returnValue($count));
+        $agreement = $this->getMock('Magento\Paypal\Model\Billing\Agreement', [], [], '', false);
+        $agreement->expects($this->once())
+            ->method('getAvailableCustomerBillingAgreements')
+            ->with(1)
+            ->will($this->returnValue($agreementCollection));
+        $this->agreementFactory->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($agreement));
+        $this->assertEquals($count > 0, $this->callAroundIsApplicable($proceed, $paymentMethod, $quote));
+    }
+
+    public function aroundIsApplicableDataProvider()
+    {
+        return [[0], [1], [2]];
+    }
+
+    /**
+     * @param bool $result
+     * @param PaymentMethodChecksInterface $paymentMethod
+     * @param Quote $quote
+     * @return \Closure
+     */
+    private function getProceedClosure($result, PaymentMethodChecksInterface $paymentMethod, Quote $quote)
+    {
+        $self = $this;
+        return function ($parameter1, $parameter2) use ($result, $paymentMethod, $quote, $self) {
+            $self->assertSame($paymentMethod, $parameter1);
+            $self->assertSame($quote, $parameter2);
+            return $result;
+        };
+    }
+
+    /**
+     * Get payment method parameter
+     *
+     * @param string $code
+     * @return PaymentMethodChecksInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private function getPaymentMethod($code)
+    {
+        $paymentMethod = $this->getMockForAbstractClass('Magento\Payment\Model\Checks\PaymentMethodChecksInterface');
+        $paymentMethod->expects($this->any())
+            ->method('getCode')
+            ->will($this->returnValue($code));
+        return $paymentMethod;
+    }
+
+    /**
+     * Get quote parameter
+     *
+     * @param mixed $customerId
+     * @return Quote|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private function getQuote($customerId)
+    {
+        $quote = $this->getMock('Magento\Sales\Model\Quote', ['__wakeup'], [], '', false);
+        $quote->setCustomerId($customerId);
+        return $quote;
+    }
+
+    /**
+     * Call aroundIsApplicable method
+     *
+     * @param \Closure $proceed
+     * @param PaymentMethodChecksInterface $paymentMethod
+     * @param Quote $quote
+     * @return bool
+     */
+    private function callAroundIsApplicable(
+        \Closure $proceed,
+        PaymentMethodChecksInterface $paymentMethod,
+        Quote $quote
+    ) {
+        $specification = $this->getMockForAbstractClass('Magento\Payment\Model\Checks\SpecificationInterface');
+        return $this->model->aroundIsApplicable($specification, $proceed, $paymentMethod, $quote);
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowlinkTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowlinkTest.php
index 2d6e8d5c1f1b8d35b1e70cf91517004ff572de26..b2eb2eba5e84d6f5f8ec14c401c31ea2ee3bd58e 100644
--- a/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowlinkTest.php
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowlinkTest.php
@@ -47,14 +47,10 @@ class PayflowlinkTest extends \PHPUnit_Framework_TestCase
     {
         $this->store = $this->getMock('Magento\Store\Model\Store', [], [], '', false);
         $storeManager = $this->getMock('Magento\Store\Model\StoreManagerInterface');
-        $storeManager->expects($this->any())
-            ->method('getStore')
-            ->will($this->returnValue($this->store));
+        $storeManager->expects($this->any())->method('getStore')->will($this->returnValue($this->store));
         $this->paypalConfig = $this->getMock('Magento\Paypal\Model\Config', [], [], '', false);
         $configFactory = $this->getMock('Magento\Paypal\Model\ConfigFactory', ['create']);
-        $configFactory->expects($this->any())
-            ->method('create')
-            ->will($this->returnValue($this->paypalConfig));
+        $configFactory->expects($this->any())->method('create')->will($this->returnValue($this->paypalConfig));
         $this->payflowRequest = $this->getMock('Magento\Paypal\Model\Payflow\Request', [], [], '', false);
         $this->payflowRequest->expects($this->any())
             ->method('__call')
@@ -65,11 +61,37 @@ class PayflowlinkTest extends \PHPUnit_Framework_TestCase
                 return null;
             }));
         $requestFactory = $this->getMock('Magento\Paypal\Model\Payflow\RequestFactory', ['create']);
-        $requestFactory->expects($this->any())
-            ->method('create')
-            ->will($this->returnValue($this->payflowRequest));
+        $requestFactory->expects($this->any())->method('create')->will($this->returnValue($this->payflowRequest));
         $this->infoInstance = $this->getMock('Magento\Sales\Model\Order\Payment', [], [], '', false);
 
+        $client = $this->getMock(
+            'Magento\Framework\HTTP\ZendClient',
+            [
+                'setUri',
+                'setConfig',
+                'setMethod',
+                'setParameterPost',
+                'setHeaders',
+                'setUrlEncodeBody',
+                'request',
+                'getBody'
+            ],
+            [],
+            '',
+            false
+        );
+        $client->expects($this->any())->method('create')->will($this->returnSelf());
+        $client->expects($this->any())->method('setUri')->will($this->returnSelf());
+        $client->expects($this->any())->method('setConfig')->will($this->returnSelf());
+        $client->expects($this->any())->method('setMethod')->will($this->returnSelf());
+        $client->expects($this->any())->method('setParameterPost')->will($this->returnSelf());
+        $client->expects($this->any())->method('setHeaders')->will($this->returnSelf());
+        $client->expects($this->any())->method('setUrlEncodeBody')->will($this->returnSelf());
+        $client->expects($this->any())->method('request')->will($this->returnSelf());
+        $client->expects($this->any())->method('getBody')->will($this->returnValue('RESULT name=value&name2=value2'));
+        $clientFactory = $this->getMock('Magento\Framework\HTTP\ZendClientFactory', ['create'], [], '', false);
+        $clientFactory->expects($this->any())->method('create')->will($this->returnValue($client));
+
         $helper = new ObjectManagerHelper($this);
         $this->model = $helper->getObject(
             'Magento\Paypal\Model\Payflowlink',
@@ -77,30 +99,22 @@ class PayflowlinkTest extends \PHPUnit_Framework_TestCase
                 'storeManager' => $storeManager,
                 'configFactory' => $configFactory,
                 'requestFactory' => $requestFactory,
+                'httpClientFactory' => $clientFactory
             ]
         );
         $this->model->setInfoInstance($this->infoInstance);
     }
 
-    /**
-     * @expectedException \Magento\Framework\Model\Exception
-     */
     public function testInitialize()
     {
         $order = $this->getMock('Magento\Sales\Model\Order', [], [], '', false);
-        $this->infoInstance->expects($this->any())
-            ->method('getOrder')
-            ->will($this->returnValue($order));
-        $this->paypalConfig->expects($this->once())
-            ->method('getBuildNotationCode')
+        $this->infoInstance->expects($this->any())->method('getOrder')->will($this->returnValue($order));
+        $this->infoInstance->expects($this->any())->method('setAdditionalInformation')->will($this->returnSelf());
+        $this->paypalConfig->expects($this->once())->method('getBuildNotationCode')
             ->will($this->returnValue('build notation code'));
-        $this->payflowRequest->expects($this->once())
-            ->method('setData')
-            ->with('BNCODE', 'build notation code')
+        $this->payflowRequest->expects($this->once())->method('setData')->with('BNCODE', 'build notation code')
             ->will($this->returnSelf());
-        $this->model->initialize(
-            \Magento\Paypal\Model\Config::PAYMENT_ACTION_AUTH,
-            new \Magento\Framework\Object()
-        );
+        $stateObject = new \Magento\Framework\Object();
+        $this->model->initialize(\Magento\Paypal\Model\Config::PAYMENT_ACTION_AUTH, $stateObject);
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowproTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowproTest.php
index 50467279928cc6381697363c8c199b85a34b9378..df13e41db1fc45385d967f4f785b1b8cb7ab0d8b 100644
--- a/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowproTest.php
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowproTest.php
@@ -53,10 +53,41 @@ class PayflowproTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
+        $client = $this->getMock(
+            'Magento\Framework\HTTP\ZendClient',
+            [
+                'setUri',
+                'setConfig',
+                'setMethod',
+                'setParameterPost',
+                'setHeaders',
+                'setUrlEncodeBody',
+                'request',
+                'getBody'
+            ],
+            [],
+            '',
+            false
+        );
+        $client->expects($this->any())->method('create')->will($this->returnSelf());
+        $client->expects($this->any())->method('setUri')->will($this->returnSelf());
+        $client->expects($this->any())->method('setConfig')->will($this->returnSelf());
+        $client->expects($this->any())->method('setMethod')->will($this->returnSelf());
+        $client->expects($this->any())->method('setParameterPost')->will($this->returnSelf());
+        $client->expects($this->any())->method('setHeaders')->will($this->returnSelf());
+        $client->expects($this->any())->method('setUrlEncodeBody')->will($this->returnSelf());
+        $client->expects($this->any())->method('request')->will($this->returnSelf());
+        $client->expects($this->any())->method('getBody')->will($this->returnValue('RESULT name=value&name2=value2'));
+        $clientFactory = $this->getMock('Magento\Framework\HTTP\ZendClientFactory', ['create'], [], '', false);
+        $clientFactory->expects($this->any())->method('create')->will($this->returnValue($client));
+
         $this->_helper = new \Magento\TestFramework\Helper\ObjectManager($this);
         $this->_model = $this->_helper->getObject(
             'Magento\Paypal\Model\Payflowpro',
-            ['configFactory' => $this->_configFactory]
+            [
+                'configFactory' => $this->_configFactory,
+                'httpClientFactory' => $clientFactory
+            ]
         );
     }
 
@@ -98,17 +129,15 @@ class PayflowproTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * test for _buildBasicRequest (BDCODE) and catch exception of response
+     * test for _buildBasicRequest (BDCODE)
      */
-    public function testFetchTransactionInfoForBNException()
+    public function testFetchTransactionInfoForBN()
     {
         $this->_configFactory->expects($this->once())->method('create')->will($this->returnSelf());
         $this->_configFactory->expects($this->once())->method('getBuildNotationCode')
             ->will($this->returnValue('BNCODE'));
-        $payment = $this->getMock('Magento\Payment\Model\Info', [], [], '', false);
-        $this->setExpectedException(
-            'Magento\Framework\Model\Exception', 'User authentication failed'
-        );
+        $payment = $this->getMock('Magento\Payment\Model\Info', ['setTransactionId', '__wakeup'], [], '', false);
+        $payment->expects($this->once())->method('setTransactionId')->will($this->returnSelf());
         $this->_model->fetchTransactionInfo($payment, 'AD49G8N825');
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/SalesRule/Model/RulesApplierTest.php b/dev/tests/unit/testsuite/Magento/SalesRule/Model/RulesApplierTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..449dbb6acd72f2fc64ef8640b53149495fe00bf8
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/SalesRule/Model/RulesApplierTest.php
@@ -0,0 +1,215 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\SalesRule\Model;
+
+class RulesApplierTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\SalesRule\Model\RulesApplier
+     */
+    protected $rulesApplier;
+
+    /**
+     * @var \Magento\SalesRule\Model\Rule\Action\Discount\CalculatorFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $calculatorFactory;
+
+    /**
+     * @var \Magento\Framework\Event\Manager|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $eventManager;
+
+    /**
+     * @var \Magento\SalesRule\Model\Utility|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $validatorUtility;
+
+    public function setUp()
+    {
+        $this->calculatorFactory = $this->getMock(
+            'Magento\SalesRule\Model\Rule\Action\Discount\CalculatorFactory',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->eventManager = $this->getMock(
+            'Magento\Framework\Event\Manager',
+            ['dispatch'],
+            [],
+            '',
+            false
+        );
+        $this->validatorUtility = $this->getMock(
+            'Magento\SalesRule\Model\Utility',
+            ['canProcessRule', 'minFix', 'deltaRoundingFix', 'getItemQty'],
+            [],
+            '',
+            false
+        );
+
+
+        $this->rulesApplier = new \Magento\SalesRule\Model\RulesApplier(
+            $this->calculatorFactory,
+            $this->eventManager,
+            $this->validatorUtility
+        );
+    }
+
+    public function testApplyRulesWhenRuleWithStopRulesProcessingIsUsed()
+    {
+        $positivePrice = 1;
+        $skipValidation = true;
+        $item = $this->getPreparedItem();
+        $couponCode = 111;
+
+        $ruleId = 1;
+        $appliedRuleIds = [$ruleId => $ruleId];
+
+        /**
+         * @var \Magento\SalesRule\Model\Rule|\PHPUnit_Framework_MockObject_MockObject $ruleWithStopFurtherProcessing
+         */
+        $ruleWithStopFurtherProcessing = $this->getMock(
+            'Magento\SalesRule\Model\Rule',
+            ['getStoreLabel', 'getCouponType', 'getRuleId', '__wakeup'],
+            [],
+            '',
+            false
+        );
+        /** @var \Magento\SalesRule\Model\Rule|\PHPUnit_Framework_MockObject_MockObject $ruleThatShouldNotBeRun */
+        $ruleThatShouldNotBeRun = $this->getMock(
+            'Magento\SalesRule\Model\Rule',
+            ['getStopRulesProcessing', '__wakeup'],
+            [],
+            '',
+            false
+        );
+
+        $ruleWithStopFurtherProcessing->setName('ruleWithStopFurtherProcessing');
+        $ruleThatShouldNotBeRun->setName('ruleThatShouldNotBeRun');
+        $rules = [$ruleWithStopFurtherProcessing, $ruleThatShouldNotBeRun];
+
+        $item->setDiscountCalculationPrice($positivePrice);
+        $item->setData('calculation_price', $positivePrice);
+
+        $this->validatorUtility->expects($this->atLeastOnce())
+            ->method('canProcessRule')
+            ->will(
+                $this->returnValue(true)
+            );
+        $ruleWithStopFurtherProcessing->expects($this->any())
+            ->method('getRuleId')
+            ->will($this->returnValue($ruleId));
+        $this->applyRule($item, $ruleWithStopFurtherProcessing);
+        $ruleWithStopFurtherProcessing->setStopRulesProcessing(true);
+        $ruleThatShouldNotBeRun->expects($this->never())
+            ->method('getStopRulesProcessing');
+        $result = $this->rulesApplier->applyRules($item, $rules, $skipValidation, $couponCode);
+        $this->assertEquals($appliedRuleIds, $result);
+    }
+
+    /**
+     * @return \Magento\Sales\Model\Quote\Item\AbstractItem|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function getPreparedItem()
+    {
+        /** @var \Magento\Sales\Model\Quote\Address|\PHPUnit_Framework_MockObject_MockObject $address */
+        $address = $this->getMock(
+            'Magento\Sales\Model\Quote\Address',
+            [
+                'getQuote',
+                'setCouponCode',
+                'setAppliedRuleIds',
+                '__wakeup'
+            ],
+            [],
+            '',
+            false
+        );
+        /** @var \Magento\Sales\Model\Quote\Item\AbstractItem|\PHPUnit_Framework_MockObject_MockObject $item */
+        $item = $this->getMock(
+            'Magento\Sales\Model\Quote\Item',
+            [
+                'setDiscountAmount',
+                'setBaseDiscountAmount',
+                'setDiscountPercent',
+                'getAddress',
+                'setAppliedRuleIds',
+                '__wakeup'
+            ],
+            [],
+            '',
+            false
+        );
+        $quote = $this->getMock('Magento\Sales\Model\Quote', ['getStore', '__wakeUp'], [], '', false);
+        $item->expects($this->any())->method('getAddress')->will($this->returnValue($address));
+        $address->expects($this->any())
+            ->method('getQuote')
+            ->will($this->returnValue($quote));
+
+        return $item;
+    }
+
+    protected function applyRule($item, $rule)
+    {
+        $qty = 2;
+        $discountCalc = $this->getMock(
+            'Magento\SalesRule\Model\Rule\Action\Discount',
+            ['fixQuantity', 'calculate'],
+            [],
+            '',
+            false
+        );
+        $discountData = $this->getMock(
+            'Magento\SalesRule\Model\Rule\Action\Discount\Data',
+            [],
+            [
+                'amount' => 30,
+                'baseAmount' => 30,
+                'originalAmount' => 30,
+                'baseOriginalAmount' => 30
+            ],
+            '',
+            false
+        );
+        $this->validatorUtility->expects($this->any())
+            ->method('getItemQty')
+            ->with($this->anything(), $this->anything())
+            ->will($this->returnValue($qty));
+        $discountCalc->expects($this->any())
+            ->method('fixQuantity')
+            ->with($this->equalTo($qty), $this->equalTo($rule))
+            ->will($this->returnValue($qty));
+
+        $discountCalc->expects($this->any())
+            ->method('calculate')
+            ->with($this->equalTo($rule), $this->equalTo($item), $this->equalTo($qty))
+            ->will($this->returnValue($discountData));
+        $this->calculatorFactory->expects($this->any())
+            ->method('create')
+            ->with($this->anything())
+            ->will($this->returnValue($discountCalc));
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/SalesRule/Model/ValidatorTest.php b/dev/tests/unit/testsuite/Magento/SalesRule/Model/ValidatorTest.php
index 3d8e21bf9d0b5d02ec85e3e9e4522c182fffe976..a2c29e03ce83d9ba41162ae13eb947f9a0912b1f 100644
--- a/dev/tests/unit/testsuite/Magento/SalesRule/Model/ValidatorTest.php
+++ b/dev/tests/unit/testsuite/Magento/SalesRule/Model/ValidatorTest.php
@@ -30,6 +30,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
      */
     protected $model;
 
+
     protected function setUp()
     {
         // @TODO Re-write test according to standards of writing test (e.g do not mock tested class)
@@ -108,11 +109,18 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
         /** @var \Magento\SalesRule\Model\Validator|\PHPUnit_Framework_MockObject_MockObject $validator */
         $validator = $this->getMock(
             'Magento\SalesRule\Model\Validator',
-            array('applyRules', '__wakeup'),
+            array('__wakeup'),
             array(),
             '',
             false
         );
+        $rulesApplier = $this->getMock(
+            'Magento\SalesRule\Model\Validator\RulesApplier',
+            ['applyRules', '__wakeup'],
+            [],
+            '',
+            false
+        );
 
         /** @var \Magento\Sales\Model\Quote\Item\AbstractItem|\PHPUnit_Framework_MockObject_MockObject $item */
         $item = $this->getMock('Magento\Sales\Model\Quote\Item', array('__wakeup'), array(), '', false);
@@ -122,7 +130,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
         $item->setData('calculation_price', $negativePrice);
 
         // 3. Set expectations
-        $validator->expects($this->never())->method('applyRules');
+        $rulesApplier->expects($this->never())->method('applyRules');
 
         // 4. Run tested method
         $validator->process($item);
@@ -137,7 +145,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
         /** @var \Magento\SalesRule\Model\Validator|\PHPUnit_Framework_MockObject_MockObject $validator */
         $validator = $this->getMock(
             'Magento\SalesRule\Model\Validator',
-            array('applyRules', '__wakeup'),
+            array('__wakeup'),
             array(),
             '',
             false
@@ -164,101 +172,49 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals(0, $item->getDiscountPercent());
     }
 
-    public function testApplyRulesWhenRuleWithStopRulesProcessingIsUsed()
+    public function testApplyRulesThatAppliedRuleIdsAreCollected()
     {
         $positivePrice = 1;
+        $ruleId1 = 123;
+        $ruleId2 = 234;
+        $expectedRuleIds = array($ruleId1 => $ruleId1, $ruleId2 => $ruleId2);
 
         // 1. Get mocks
-        /** @var \Magento\SalesRule\Model\Validator|\PHPUnit_Framework_MockObject_MockObject $validator */
-        $validator = $this->getMock(
-            'Magento\SalesRule\Model\Validator',
-            array('applyRule', 'setAppliedRuleIds', '_canProcessRule', '_getRules', '__wakeup'),
-            array(),
-            '',
-            false
-        );
-        /** @var \Magento\Sales\Model\Quote\Address|\PHPUnit_Framework_MockObject_MockObject $address */
-        $address = $this->getMock('Magento\Sales\Model\Quote\Address', array('__wakeup'), array(), '', false);
-        /** @var \Magento\Sales\Model\Quote\Item\AbstractItem|\PHPUnit_Framework_MockObject_MockObject $item */
-        $item = $this->getMock('Magento\Sales\Model\Quote\Item', array('getAddress', '__wakeup'), array(), '', false);
-        /**
-         * @var \Magento\SalesRule\Model\Rule|\PHPUnit_Framework_MockObject_MockObject $ruleWithStopFurtherProcessing
-         */
-        $ruleWithStopFurtherProcessing = $this->getMock(
-            'Magento\SalesRule\Model\Rule',
-            array('__wakeup'),
-            array(),
+        $rulesApplier = $this->getMock(
+            'Magento\SalesRule\Model\RulesApplier',
+            ['applyRules', 'setAppliedRuleIds'],
+            [],
             '',
             false
         );
-        /** @var \Magento\SalesRule\Model\Rule|\PHPUnit_Framework_MockObject_MockObject $ruleThatShouldNotBeRun */
-        $ruleThatShouldNotBeRun = $this->getMock(
-            'Magento\SalesRule\Model\Rule',
-            array('__wakeup'),
-            array(),
+        $context = $this->getMock('Magento\Framework\Model\Context', [], [], '', false);
+        $registry = $this->getMock('Magento\Framework\Registry', [], [], '', false);
+        $collectionFactory = $this->getMock(
+            'Magento\SalesRule\Model\Resource\Rule\CollectionFactory',
+            [],
+            [],
             '',
             false
         );
+        $taxData = $this->getMock('Magento\Tax\Helper\Data', [], [], '', false);
+        $utility = $this->getMock('Magento\SalesRule\Model\Utility', [], [], '', false);
 
-        $item->expects($this->any())->method('getAddress')->will($this->returnValue($address));
-        $ruleWithStopFurtherProcessing->setName('ruleWithStopFurtherProcessing');
-        $ruleThatShouldNotBeRun->setName('ruleThatShouldNotBeRun');
-        $rules = array($ruleWithStopFurtherProcessing, $ruleThatShouldNotBeRun);
-        $validator->expects($this->any())->method('_getRules')->will($this->returnValue($rules));
-
-        // 2. Set fixtures, provide tested code isolation
-        $item->setDiscountCalculationPrice($positivePrice);
-        $item->setData('calculation_price', $positivePrice);
-        $validator->setSkipActionsValidation(true);
-        $validator->expects($this->any())->method('_canProcessRule')->will($this->returnValue(true));
-        $ruleWithStopFurtherProcessing->setStopRulesProcessing(true);
-
-        // 3. Set expectations
-        $callback = function ($rule) use ($ruleThatShouldNotBeRun) {
-            /** @var $rule \Magento\SalesRule\Model\Rule|\PHPUnit_Framework_MockObject_MockObject */
-            if ($rule->getName() == $ruleThatShouldNotBeRun->getName()) {
-                $this->fail('Rule should not be run after applying rule that stops further rules processing');
-            }
-
-            return true;
-        };
-        $validator->expects(
-            $this->any()
-        )->method(
-            'applyRule'
-        )->with(
-            $this->anything(),
-            $this->callback($callback),
-            $this->anything()
-        );
-
-        // 4. Run tested method
-        $validator->process($item);
-
-        // 5. Set new expectations
-        $validator->expects($this->never())->method('applyRule');
-        //No rules should be applied further
-
-        // 6. Run tested method again
-        $validator->process($item);
-    }
-
-    public function testApplyRulesThatAppliedRuleIdsAreCollected()
-    {
-        $positivePrice = 1;
-        $ruleId1 = 123;
-        $ruleId2 = 234;
-        $expectedRuleIds = array($ruleId1 => $ruleId1, $ruleId2 => $ruleId2);
-
-        // 1. Get mocks
         /** @var \Magento\SalesRule\Model\Validator|\PHPUnit_Framework_MockObject_MockObject $validator */
         $validator = $this->getMock(
             'Magento\SalesRule\Model\Validator',
-            array('applyRule', '_getRules', '_canProcessRule', 'setAppliedRuleIds', '__wakeup'),
-            array(),
+            ['_getRules', '_canProcessRule', '__wakeup'],
+            [
+                'context' => $context,
+                'registry' => $registry,
+                'collectionFactory' => $collectionFactory,
+                'taxData' => $taxData,
+                'utility' => $utility,
+                'rulesApplier' => $rulesApplier
+            ],
             '',
-            false
+            true
         );
+
         /** @var \Magento\Sales\Model\Quote\Item\AbstractItem|\PHPUnit_Framework_MockObject_MockObject $item */
         $item = $this->getMock('Magento\Sales\Model\Quote\Item', array('getAddress', '__wakeup'), array(), '', false);
         /** @var \Magento\SalesRule\Model\Rule|\PHPUnit_Framework_MockObject_MockObject $rule */
@@ -274,108 +230,23 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
         $item->setDiscountCalculationPrice($positivePrice);
         $item->setData('calculation_price', $positivePrice);
         $validator->setSkipActionsValidation(true);
-        $validator->expects($this->any())->method('_canProcessRule')->will($this->returnValue(true));
 
         // 3. Set expectations
-        $validator->expects($this->once())->method('setAppliedRuleIds')->with($this->anything(), $expectedRuleIds);
-
-        // 4. Run tested method again
-        $validator->process($item);
-    }
-
-    public function testApplyRule()
-    {
-        $positivePrice = 1;
-
-        // 1. Get mocks
-        /** @var \Magento\SalesRule\Model\Validator|\PHPUnit_Framework_MockObject_MockObject $validator */
-        $validator = $this->getMockBuilder(
-            'Magento\SalesRule\Model\Validator'
-        )->setMethods(
-            array(
-                'getDiscountData',
-                'setDiscountData',
-                '_addDiscountDescription',
-                '_maintainAddressCouponCode',
-                '_canProcessRule',
-                'setAppliedRuleIds',
-                '_getRules',
-                '__wakeup'
+        $rulesApplier->expects($this->once())
+            ->method('applyRules')
+            ->with(
+                $this->equalTo($item),
+                $this->equalTo($rules),
+                $this->anything(),
+                $this->anything()
             )
-        )->disableOriginalConstructor()->getMock();
-        $rule = $this->getMockBuilder(
-            'Magento\SalesRule\Model\Rule'
-        )->disableOriginalConstructor()->setMethods(
-            array()
-        )->getMock();
-        /** @var \Magento\Sales\Model\Quote\Item\AbstractItem|\PHPUnit_Framework_MockObject_MockObject $item */
-        $item = $this->getMock('Magento\Sales\Model\Quote\Item', array('getAddress', '__wakeup'), array(), '', false);
-        $discountData = $this->getMockBuilder('Magento\SalesRule\Model\Rule\Action\Discount\Data')->getMock();
-
-        // 2.Provide tested code isolation
-        $item->setDiscountCalculationPrice($positivePrice);
-        $item->setData('calculation_price', $positivePrice);
-        $validator->setSkipActionsValidation(true);
-        $validator->expects($this->any())->method('_canProcessRule')->will($this->returnValue(true));
-        $validator->expects($this->any())->method('_getRules')->will($this->returnValue(array($rule)));
-        $validator->expects($this->any())->method('getDiscountData')->will($this->returnValue($discountData));
-
-        // 3. Set expectations
-        $validator->expects($this->any())->method('setDiscountData')->with($discountData);
+            ->will($this->returnValue($expectedRuleIds));
+        $rulesApplier->expects($this->once())->method('setAppliedRuleIds')->with($this->anything(), $expectedRuleIds);
 
         // 4. Run tested method again
         $validator->process($item);
     }
 
-    public function testSetAppliedRuleIds()
-    {
-        $positivePrice = 1;
-        $previouslySetRuleIds = array(1, 2, 4);
-        $exampleRuleIds = array(1, 2, 3, 5);
-        $expectedRuleIds = '1,2,3,5';
-        $expectedMergedRuleIds = '1,2,3,4,5';
-
-        // 1. Get mocks
-        /** @var \Magento\SalesRule\Model\Validator|\PHPUnit_Framework_MockObject_MockObject $validator */
-        $validator = $this->getMock(
-            'Magento\SalesRule\Model\Validator',
-            array('applyRules', '__wakeup'),
-            array(),
-            '',
-            false
-        );
-        /** @var \Magento\Sales\Model\Quote\Item\AbstractItem|\PHPUnit_Framework_MockObject_MockObject $item */
-        $item = $this->getMock(
-            'Magento\Sales\Model\Quote\Item',
-            array('getAddress', 'getQuote', '__wakeup'),
-            array(),
-            '',
-            false
-        );
-        /** @var \Magento\Sales\Model\Quote\Address|\PHPUnit_Framework_MockObject_MockObject $address */
-        $address = $this->getMock('Magento\Sales\Model\Quote\Address', array('__wakeup'), array(), '', false);
-        /** @var \Magento\Sales\Model\Quote|\PHPUnit_Framework_MockObject_MockObject $quote */
-        $quote = $this->getMock('Magento\Sales\Model\Quote', array('__wakeup'), array(), '', false);
-        $item->expects($this->any())->method('getAddress')->will($this->returnValue($address));
-        $item->expects($this->any())->method('getQuote')->will($this->returnValue($quote));
-
-        // 2. Set fixtures
-        $item->setDiscountCalculationPrice($positivePrice);
-        $item->setData('calculation_price', $positivePrice);
-        $validator->expects($this->any())->method('applyRules')->will($this->returnValue($exampleRuleIds));
-        $address->setAppliedRuleIds($previouslySetRuleIds);
-        $quote->setAppliedRuleIds($previouslySetRuleIds);
-
-        // 3. Run tested method
-        $validator->process($item);
-
-        // 4. Check expected result
-        $this->assertEquals($expectedRuleIds, $item->getAppliedRuleIds());
-
-        $this->assertObjectHasRuleIdsSet($expectedMergedRuleIds, $item->getAddress());
-        $this->assertObjectHasRuleIdsSet($expectedMergedRuleIds, $item->getQuote());
-    }
-
     /**
      * @param $expectedMergedRuleIds
      * @param \Magento\Sales\Model\Quote\Address|\Magento\Sales\Model\Quote $object
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/CalculatorFactoryTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/CalculatorFactoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2318f8ffa6553e543a2689cd04a600733efadd12
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/CalculatorFactoryTest.php
@@ -0,0 +1,214 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Model\Calculation;
+
+use Magento\Customer\Service\V1\Data\Address;
+use Magento\TestFramework\Helper\ObjectManager;
+
+/**
+ * Test class for \Magento\Tax\Model\CalculatorFactory
+ */
+class CalculatorFactoryTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\TestFramework\Helper\ObjectManager
+     */
+    public $objectManager;
+
+    public function setUp()
+    {
+        $this->objectManager = new ObjectManager($this);
+    }
+
+    /**
+     * @param string $type Type of calculator
+     * @param int $storeId
+     * @param Address $billingAddress
+     * @param Address $shippingAddress
+     * @param null|int $customerTaxClassId
+     * @param null|int $customerId
+     * @param \Magento\Tax\Model\Calculation\AbstractCalculator $expectedInstanceType
+     *  expected type of calculator instance
+     *
+     * @dataProvider createDataProvider
+     */
+    public function testCreate(
+        $type,
+        $storeId,
+        $billingAddress,
+        $shippingAddress,
+        $customerTaxClassId,
+        $customerId,
+        $expectedInstanceType
+    ) {
+        $instanceMock = $this->getMockBuilder($expectedInstanceType)->disableOriginalConstructor()->getMock();
+        $objectManagerMock = $this->getMockBuilder('Magento\Framework\ObjectManager')->getMock();
+
+        // Verify create() is called with correct concrete type
+        $objectManagerMock->expects($this->once())
+            ->method('create')
+            ->with($expectedInstanceType, ['storeId' => $storeId])
+            ->will($this->returnValue($instanceMock));
+
+        /** @var CalculatorFactory $calculatorFactory */
+        $calculatorFactory = $this->objectManager->getObject(
+            'Magento\Tax\Model\Calculation\CalculatorFactory',
+            ['objectManager' => $objectManagerMock]
+        );
+
+        // Verify billing is set correctly if passed in
+        if ($billingAddress != null) {
+            $instanceMock->expects($this->once())
+                ->method('setBillingAddress')
+                ->with($billingAddress);
+        } else {
+            $instanceMock->expects($this->never())
+                ->method('setBillingAddress');
+        }
+
+        // Verify shipping is set correctly if passed in
+        if ($shippingAddress != null) {
+            $instanceMock->expects($this->once())
+                ->method('setShippingAddress')
+                ->with($shippingAddress);
+        } else {
+            $instanceMock->expects($this->never())
+                ->method('setShippingAddress');
+        }
+
+        // Verify customerTaxClassId is set correctly if passed in
+        if ($customerTaxClassId != null) {
+            $instanceMock->expects($this->once())
+                ->method('setCustomerTaxClassId')
+                ->with($customerTaxClassId);
+        } else {
+            $instanceMock->expects($this->never())
+                ->method('setCustomerTaxClassId');
+        }
+
+        // Verify customerId is set correctly if passed in
+        if ($customerId != null) {
+            $instanceMock->expects($this->once())
+                ->method('setCustomerId')
+                ->with($customerId);
+        } else {
+            $instanceMock->expects($this->never())
+                ->method('setCustomerId');
+        }
+
+        // Call create()
+        $calculator = $calculatorFactory
+            ->create($type, $storeId, $billingAddress, $shippingAddress, $customerTaxClassId, $customerId);
+
+        // Verify correct type is returned
+        $this->assertInstanceOf($expectedInstanceType, $calculator);
+    }
+
+    /**
+     * Returns a set of 'true' and 'false' parameters for each of the setter/getter method pairs
+     *
+     * @return array
+     */
+    public function createDataProvider()
+    {
+        $billingAddressMock = $this->getMockBuilder('\Magento\Customer\Service\V1\Data\Address')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $shippingAddressMock = $this->getMockBuilder('\Magento\Customer\Service\V1\Data\Address')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        return [
+            'Unit' => [
+                CalculatorFactory::CALC_UNIT_BASE,
+                1,
+                null,
+                null,
+                null,
+                null,
+                'Magento\Tax\Model\Calculation\UnitBaseCalculator'
+            ],
+            'Row HasBilling' => [
+                CalculatorFactory::CALC_ROW_BASE,
+                2,
+                $billingAddressMock,
+                null,
+                null,
+                null,
+                'Magento\Tax\Model\Calculation\RowBaseCalculator'
+            ],
+            'Row HasCustomerTaxClassId' => [
+                CalculatorFactory::CALC_ROW_BASE,
+                3,
+                null,
+                null,
+                123,
+                null,
+                'Magento\Tax\Model\Calculation\RowBaseCalculator'
+            ],
+            'Total HasShipping' => [
+                CalculatorFactory::CALC_TOTAL_BASE,
+                1,
+                null,
+                $shippingAddressMock,
+                null,
+                null,
+                'Magento\Tax\Model\Calculation\TotalBaseCalculator'
+            ],
+            'Total HasShipping HasBilling HasCustomerTaxClassId' => [
+                CalculatorFactory::CALC_TOTAL_BASE,
+                1,
+                $billingAddressMock,
+                $shippingAddressMock,
+                1,
+                null,
+                'Magento\Tax\Model\Calculation\TotalBaseCalculator'
+            ],
+            'Total HasShipping HasBilling HasCustomerTaxClassId, HasCustomer' => [
+                CalculatorFactory::CALC_TOTAL_BASE,
+                1,
+                $billingAddressMock,
+                $shippingAddressMock,
+                1,
+                1,
+                'Magento\Tax\Model\Calculation\TotalBaseCalculator'
+            ],
+        ];
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage Unknown calculation type: NOT_A_TYPE
+     */
+    public function testCreateInvalid()
+    {
+        /** @var CalculatorFactory $calculatorFactory */
+        $calculatorFactory = $this->objectManager->getObject(
+            'Magento\Tax\Model\Calculation\CalculatorFactory'
+        );
+
+        // Call create() with a bad type to generate exception
+        $calculatorFactory->create('NOT_A_TYPE', 1);
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/RowBaseAndTotalBaseCalculatorTestCase.php b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/RowBaseAndTotalBaseCalculatorTestCase.php
new file mode 100644
index 0000000000000000000000000000000000000000..ede59e89b3b90c11ded32cb804ff9a0822213e1a
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/RowBaseAndTotalBaseCalculatorTestCase.php
@@ -0,0 +1,334 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Model\Calculation;
+
+use Magento\TestFramework\Helper\ObjectManager;
+use Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder;
+
+class RowBaseAndTotalBaseCalculatorTestCase extends \PHPUnit_Framework_TestCase
+{
+    const STORE_ID = 2300;
+    const QUANTITY = 1;
+    const UNIT_PRICE = 500;
+    const RATE = 10;
+    const STORE_RATE = 11;
+
+    const CODE = 'CODE';
+    const TYPE = 'TYPE';
+
+    const ONCE = 'once';
+    const MOCK_METHOD_NAME = 'mock_method_name';
+    const MOCK_VALUE = 'mock_value';
+    const WITH_ARGUMENT = 'with_argument';
+    const EXPECTED_VALUE = "some_return_object";
+
+    /** @var ObjectManager */
+    protected $objectManager;
+
+    /** @var \Magento\Tax\Service\V1\Data\TaxDetails\ItemBuilder | \PHPUnit_Framework_MockObject_MockObject */
+    protected $mockTaxItemDetailsBuilder;
+
+    /** @var \Magento\Tax\Model\Calculation | \PHPUnit_Framework_MockObject_MockObject */
+    protected $mockCalculationTool;
+
+    /** @var \Magento\Tax\Model\Config | \PHPUnit_Framework_MockObject_MockObject */
+    protected $mockConfig;
+
+    /** @var $mockItem \Magento\Tax\Service\V1\Data\QuoteDetails\Item | \PHPUnit_Framework_MockObject_MockObject */
+    protected $mockItem;
+
+    /** @var $mockAppliedTaxBuilder AppliedTaxBuilder | \PHPUnit_Framework_MockObject_MockObject */
+    protected $mockAppliedTaxBuilder;
+
+    /** @var $mockAppliedTaxRateBuilder AppliedTaxBuilder | \PHPUnit_Framework_MockObject_MockObject */
+    protected $mockAppliedTaxRateBuilder;
+
+    /** @var \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax | \PHPUnit_Framework_MockObject_MockObject */
+    protected $mockAppliedTax;
+
+    protected $addressRateRequest;
+
+    /**
+     * initialize all mocks
+     *
+     * @param bool $taxIncluded
+     */
+    public function initMocks($taxIncluded)
+    {
+        $this->initMockItem($taxIncluded);
+        $this->initMockConfig();
+        $this->initMockCalculationTool();
+        $this->initMockItemBuilder();
+        $this->initMockAppliedTaxBuilder();
+    }
+
+    public function setUp()
+    {
+        $this->objectManager = new ObjectManager($this);
+        $this->mockTaxItemDetailsBuilder = $this->getMockBuilder('\Magento\Tax\Service\V1\Data\TaxDetails\ItemBuilder')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->mockCalculationTool = $this->getMockBuilder('\Magento\Tax\Model\Calculation')
+            ->disableOriginalConstructor()
+            ->setMethods(
+                ['__wakeup', 'round', 'getRate', 'getStoreRate', 'getRateRequest', 'getAppliedRates', 'calcTaxAmount']
+            )
+            ->getMock();
+        $this->mockConfig = $this->getMockBuilder('\Magento\Tax\Model\Config')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->mockItem = $this->getMockBuilder('Magento\Tax\Service\V1\Data\QuoteDetails\Item')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->mockAppliedTaxRateBuilder = $this->getMockBuilder(
+            'Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxRateBuilder'
+        )
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->mockAppliedTaxBuilder = $this->getMockBuilder(
+            'Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder'
+        )
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->mockAppliedTax = $this->getMockBuilder(
+            'Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax'
+        )->disableOriginalConstructor()
+            ->getMock();
+
+        $this->mockAppliedTax->expects($this->any())->method('getTaxRateKey')->will($this->returnValue('taxKey'));
+        //Magento\Tax\Service\V1\Data\TaxDetails
+        $this->addressRateRequest = new \Magento\Framework\Object();
+
+    }
+
+    /**
+     * @param $calculator RowBaseCalculator|TotalBaseCalculator
+     * @return \Magento\Tax\Service\V1\Data\QuoteDetails\Item
+     */
+    public function calculate($calculator)
+    {
+        return $calculator->calculate($this->mockItem, 1);
+    }
+
+    /**
+     * init mock Items
+     *
+     * @param bool $taxIncluded
+     */
+    protected function initMockItem($taxIncluded)
+    {
+        $this->mockReturnValues(
+            $this->mockItem,
+            [
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'getDiscountAmount',
+                    self::MOCK_VALUE => 1
+                ],
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'getCode',
+                    self::MOCK_VALUE => self::CODE
+                ],
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'getType',
+                    self::MOCK_VALUE => self::TYPE
+                ],
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'getUnitPrice',
+                    self::MOCK_VALUE => self::UNIT_PRICE
+                ],
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'getTaxIncluded',
+                    self::MOCK_VALUE => $taxIncluded
+                ]
+            ]
+        );
+    }
+
+    /**
+     * init mock config
+     *
+     */
+    protected function initMockConfig()
+    {
+        $this->mockReturnValues(
+            $this->mockConfig,
+            [
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'applyTaxAfterDiscount',
+                    self::MOCK_VALUE => true
+                ]
+            ]
+        );
+    }
+
+    /**
+     * init mock calculation model
+     *
+     */
+
+    protected function initMockCalculationTool()
+    {
+        $this->mockReturnValues(
+            $this->mockCalculationTool,
+            [
+                [
+                    self::ONCE => false,
+                    self::MOCK_METHOD_NAME => 'calcTaxAmount',
+                    self::MOCK_VALUE => 1.5
+                ],
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'getRate',
+                    self::MOCK_VALUE => self::RATE
+                ],
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'getAppliedRates',
+                    self::MOCK_VALUE => [
+                        [
+                            'id' => 0,
+                            'percent' => 1.4,
+                            'rates' => [
+                                [
+                                    'code' => 'sku_1',
+                                    'title' => 'title1',
+                                    'percent' => 1.1
+                                ]
+                            ]
+                        ]
+                    ]
+                ],
+                [
+                    self::ONCE => false,
+                    self::MOCK_METHOD_NAME => 'round',
+                    self::MOCK_VALUE => 1.3
+                ]
+            ]
+        );
+    }
+
+    /**
+     * init mock applied itemBuilder
+     *
+     */
+
+    protected function initMockItemBuilder()
+    {
+        $this->mockReturnValues(
+            $this->mockTaxItemDetailsBuilder,
+            [
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'setType',
+                    self::MOCK_VALUE => self::TYPE
+                ],
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'setCode',
+                    self::MOCK_VALUE => self::CODE
+                ],
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'setRowTax',
+                    self::MOCK_VALUE => 1.3
+                ],
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'setTaxPercent',
+                    self::MOCK_VALUE => self::RATE
+                ],
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'create',
+                    self::MOCK_VALUE => self::EXPECTED_VALUE
+                ],
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'getAppliedTaxBuilder',
+                    self::MOCK_VALUE => $this->mockAppliedTaxBuilder
+                ]
+            ]
+
+        );
+    }
+
+    /**
+     * init mock appliedTaxBuilder
+     *
+     */
+    protected function initMockAppliedTaxBuilder()
+    {
+
+        $this->mockReturnValues(
+            $this->mockAppliedTaxBuilder,
+            [
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'getAppliedTaxRateBuilder',
+                    self::MOCK_VALUE => $this->mockAppliedTaxRateBuilder
+                ],
+                [
+                    self::ONCE => true,
+                    self::MOCK_METHOD_NAME => 'create',
+                    self::MOCK_VALUE => $this->mockAppliedTax
+                ]
+            ]
+        );
+    }
+
+    /**
+     * @param \PHPUnit_Framework_MockObject_MockObject $mockObject
+     * @param array $mockMap
+     */
+    private function mockReturnValues($mockObject, $mockMap)
+    {
+        foreach ($mockMap as $valueMap) {
+
+            if (isset($valueMap[self::WITH_ARGUMENT])) {
+                $mockObject->expects(
+                    $valueMap[self::ONCE] == true ? $this->once() : $this->atLeastOnce()
+                )->method($valueMap[self::MOCK_METHOD_NAME])->with($valueMap[self::WITH_ARGUMENT])
+                    ->will(
+                        $this->returnValue($valueMap[self::MOCK_VALUE])
+                    );
+            } else {
+                $mockObject->expects(
+                    $valueMap[self::ONCE] == true ? $this->once() : $this->atLeastOnce()
+                )->method($valueMap[self::MOCK_METHOD_NAME])->withAnyParameters()
+                    ->will(
+                        $this->returnValue($valueMap[self::MOCK_VALUE])
+                    );
+            }
+        }
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/RowBaseCalculatorTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/RowBaseCalculatorTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3ad65feca0906f03fdbd947afcfa36e500f07e0f
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/RowBaseCalculatorTest.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Model\Calculation;
+
+/**
+ * Class RowBaseCalculatorTest
+ *
+ */
+class RowBaseCalculatorTest extends RowBaseAndTotalBaseCalculatorTestCase
+{
+
+    /** @var RowBaseCalculator | \PHPUnit_Framework_MockObject_MockObject */
+    protected $rowBaseCalculator;
+
+    public function testCalculateWithTaxInPrice()
+    {
+        $this->initMocks(true);
+        $this->initRowBaseCalculator();
+        $this->rowBaseCalculator->expects($this->once())
+            ->method('deltaRound')->will($this->returnValue(0));
+
+        $this->assertSame(
+            self::EXPECTED_VALUE,
+            $this->calculate($this->rowBaseCalculator)
+        );
+    }
+
+    public function testCalculateWithTaxNotInPrice()
+    {
+        $this->initMocks(false);
+        $this->initRowBaseCalculator();
+        $this->rowBaseCalculator->expects($this->never())
+            ->method('deltaRound');
+
+        $this->assertSame(
+            self::EXPECTED_VALUE,
+            $this->calculate($this->rowBaseCalculator)
+        );
+    }
+
+    private function initRowBaseCalculator()
+    {
+        $taxClassService = $this->objectManager->getObject('Magento\Tax\Service\V1\TaxClassService');
+        $this->rowBaseCalculator = $this->getMockBuilder('Magento\Tax\Model\Calculation\RowBaseCalculator')
+            ->setConstructorArgs(
+                [
+                    'taxClassService' => $taxClassService,
+                    'taxDetailsItemBuilder' => $this->mockTaxItemDetailsBuilder,
+                    'calculationTool' => $this->mockCalculationTool,
+                    'config' => $this->mockConfig,
+                    'storeId' => self::STORE_ID,
+                    'addressRateRequest' => $this->addressRateRequest
+                ]
+            )->setMethods(['deltaRound'])->getMock();
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/TotalBaseCalculatorTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/TotalBaseCalculatorTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..89efb6547f1b20f3d878f1b53b391716efa3beda
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/TotalBaseCalculatorTest.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Model\Calculation;
+
+
+use Magento\Tax\Model\Calculation;
+use Magento\TestFramework\Helper\ObjectManager;
+use Magento\Tax\Service\V1\Data\QuoteDetails;
+
+/**
+ * Class TotalBaseCalculatorTest
+ *
+ */
+class TotalBaseCalculatorTest extends RowBaseAndTotalBaseCalculatorTestCase
+{
+    /** @var TotalBaseCalculator | \PHPUnit_Framework_MockObject_MockObject */
+    protected $totalBaseCalculator;
+
+    public function testCalculateWithTaxInPrice()
+    {
+        $this->initTotalBaseCalculator();
+        $this->totalBaseCalculator->expects($this->exactly(3))
+            ->method('deltaRound')->will($this->returnValue(0));
+        $this->initMocks(true);
+
+        $this->assertSame(
+            self::EXPECTED_VALUE,
+            $this->calculate($this->totalBaseCalculator)
+        );
+    }
+
+    public function testCalculateWithTaxNotInPrice()
+    {
+        $this->initTotalBaseCalculator();
+        $this->totalBaseCalculator->expects($this->exactly(2))
+            ->method('deltaRound')->will($this->returnValue(0));
+        $this->initMocks(false);
+
+        $this->assertSame(
+            self::EXPECTED_VALUE,
+            $this->calculate($this->totalBaseCalculator)
+        );
+    }
+
+    private function initTotalBaseCalculator()
+    {
+        $taxClassService = $this->objectManager->getObject('Magento\Tax\Service\V1\TaxClassService');
+        $this->totalBaseCalculator = $this->getMockBuilder('Magento\Tax\Model\Calculation\TotalBaseCalculator')
+            ->setConstructorArgs(
+                [
+                    'taxClassService' => $taxClassService,
+                    'taxDetailsItemBuilder' => $this->mockTaxItemDetailsBuilder,
+                    'calculationTool' => $this->mockCalculationTool,
+                    'config' => $this->mockConfig,
+                    'storeId' => self::STORE_ID,
+                    'addressRateRequest' => $this->addressRateRequest
+                ]
+            )->setMethods(['deltaRound'])->getMock();
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/UnitBaseCalculatorTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/UnitBaseCalculatorTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..91f33d7bcdff6a1de8926eafc9171a3dd94904f9
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/UnitBaseCalculatorTest.php
@@ -0,0 +1,199 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Model\Calculation;
+
+class UnitBaseCalculatorTest extends \PHPUnit_Framework_TestCase
+{
+    const STORE_ID = 2300;
+    const QUANTITY = 1;
+    const UNIT_PRICE = 500;
+    const RATE = 10;
+    const STORE_RATE = 11;
+
+    const CODE = 'CODE';
+    const TYPE = 'TYPE';
+    const ROW_TAX = 44.954135954136;
+
+    /** @var \Magento\Tax\Service\V1\Data\TaxDetails\ItemBuilder | \PHPUnit_Framework_MockObject_MockObject */
+    protected $mockTaxItemDetailsBuilder;
+
+    /** @var \Magento\Tax\Model\Calculation | \PHPUnit_Framework_MockObject_MockObject */
+    protected $mockCalculationTool;
+
+    /** @var \Magento\Tax\Model\Config | \PHPUnit_Framework_MockObject_MockObject */
+    protected $mockConfig;
+
+    /** @var UnitBaseCalculator */
+    protected $model;
+
+    protected $addressRateRequest;
+
+    public function setUp()
+    {
+        $this->mockTaxItemDetailsBuilder = $this->getMockBuilder('\Magento\Tax\Service\V1\Data\TaxDetails\ItemBuilder')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->mockCalculationTool = $this->getMockBuilder('\Magento\Tax\Model\Calculation')
+            ->disableOriginalConstructor()
+            ->setMethods(['__wakeup', 'round', 'getRate', 'getStoreRate', 'getRateRequest', 'getAppliedRates'])
+            ->getMock();
+        $this->mockCalculationTool->expects($this->any())
+            ->method('round')
+            ->withAnyParameters()
+            ->will($this->returnArgument(0));
+        $this->mockConfig = $this->getMockBuilder('\Magento\Tax\Model\Config')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->addressRateRequest = new \Magento\Framework\Object();
+
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $arguments = [
+            'taxDetailsItemBuilder' => $this->mockTaxItemDetailsBuilder,
+            'calculationTool'       => $this->mockCalculationTool,
+            'config'                => $this->mockConfig,
+            'storeId'               => self::STORE_ID,
+            'addressRateRequest'    => $this->addressRateRequest
+        ];
+        $this->model = $objectManager->getObject('Magento\Tax\Model\Calculation\UnitBaseCalculator', $arguments);
+    }
+
+    public function testCalculateWithTaxInPrice()
+    {
+        $mockItem = $this->getMockItem();
+        $mockItem->expects($this->once())
+            ->method('getTaxIncluded')
+            ->will($this->returnValue(true));
+
+        $this->mockConfig->expects($this->once())
+            ->method('crossBorderTradeEnabled')
+            ->will($this->returnValue(false));
+        $this->mockConfig->expects($this->once())
+            ->method('applyTaxAfterDiscount')
+            ->will($this->returnValue(true));
+
+        $this->mockCalculationTool->expects($this->once())
+            ->method('getRate')
+            ->with($this->addressRateRequest)
+            ->will($this->returnValue(self::RATE));
+        $this->mockCalculationTool->expects($this->once())
+            ->method('getStoreRate')
+            ->with($this->addressRateRequest, self::STORE_ID)
+            ->will($this->returnValue(self::STORE_RATE));
+        $this->mockCalculationTool->expects($this->once())
+            ->method('getAppliedRates')
+            ->withAnyParameters()
+            ->will($this->returnValue([]));
+
+        $mockAppliedTaxRateBuilder = $this->getMockBuilder('Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->mockTaxItemDetailsBuilder->expects($this->once())
+            ->method('getAppliedTaxBuilder')
+            ->will($this->returnValue($mockAppliedTaxRateBuilder));
+        $this->mockTaxItemDetailsBuilder->expects($this->once())
+            ->method('setCode')
+            ->with(self::CODE);
+        $this->mockTaxItemDetailsBuilder->expects($this->once())
+            ->method('setType')
+            ->with(self::TYPE);
+        $this->mockTaxItemDetailsBuilder->expects($this->once())
+            ->method('setRowTax')
+            ->with(self::ROW_TAX);
+        $expectedReturnValue = 'SOME RETURN OBJECT';
+        $this->mockTaxItemDetailsBuilder->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($expectedReturnValue));
+
+        $this->assertSame($expectedReturnValue, $this->model->calculate($mockItem, self::QUANTITY));
+    }
+
+    public function testCalculateWithTaxNotInPrice()
+    {
+        $mockItem = $this->getMockItem();
+        $mockItem->expects($this->once())
+            ->method('getTaxIncluded')
+            ->will($this->returnValue(false));
+
+        $this->mockConfig->expects($this->once())
+            ->method('applyTaxAfterDiscount')
+            ->will($this->returnValue(true));
+
+        $this->mockCalculationTool->expects($this->once())
+            ->method('getRate')
+            ->with($this->addressRateRequest)
+            ->will($this->returnValue(self::RATE));
+        $this->mockCalculationTool->expects($this->once())
+            ->method('getAppliedRates')
+            ->withAnyParameters()
+            ->will($this->returnValue([['id' => 0, 'percent' => 0, 'rates' => []]]));
+
+        $mockAppliedTaxRateBuilder = $this->getMockBuilder('Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->mockTaxItemDetailsBuilder->expects($this->once())
+            ->method('getAppliedTaxBuilder')
+            ->will($this->returnValue($mockAppliedTaxRateBuilder));
+        $this->mockTaxItemDetailsBuilder->expects($this->once())
+            ->method('setCode')
+            ->with(self::CODE);
+        $this->mockTaxItemDetailsBuilder->expects($this->once())
+            ->method('setType')
+            ->with(self::TYPE);
+        $this->mockTaxItemDetailsBuilder->expects($this->once())
+            ->method('setRowTax')
+            ->with(0.0);
+        $expectedReturnValue = 'SOME RETURN OBJECT';
+        $this->mockTaxItemDetailsBuilder->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($expectedReturnValue));
+
+        $this->assertSame($expectedReturnValue, $this->model->calculate($mockItem, self::QUANTITY));
+    }
+
+    /**
+     * @return \Magento\Tax\Service\V1\Data\QuoteDetails\Item|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function getMockItem()
+    {
+        /** @var $mockItem \Magento\Tax\Service\V1\Data\QuoteDetails\Item | \PHPUnit_Framework_MockObject_MockObject */
+        $mockItem = $this->getMockBuilder('Magento\Tax\Service\V1\Data\QuoteDetails\Item')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $mockItem->expects($this->once())
+            ->method('getDiscountAmount')
+            ->will($this->returnValue(1));
+        $mockItem->expects($this->once())
+            ->method('getCode')
+            ->will($this->returnValue(self::CODE));
+        $mockItem->expects($this->once())
+            ->method('getType')
+            ->will($this->returnValue(self::TYPE));
+        $mockItem->expects($this->once())
+            ->method('getUnitPrice')
+            ->will($this->returnValue(self::UNIT_PRICE));
+
+        return $mockItem;
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/ConfigTest.php
index 3502632adeb076bb3cb6a07574ff8523f59561dc..f61c6738555cbf803a3360bc0ee862a764c3f2b1 100644
--- a/dev/tests/unit/testsuite/Magento/Tax/Model/ConfigTest.php
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/ConfigTest.php
@@ -27,8 +27,6 @@
  */
 namespace Magento\Tax\Model;
 
-use Magento\Tax\Model\Config;
-
 class ConfigTest extends \PHPUnit_Framework_TestCase
 {
     /**
@@ -52,56 +50,21 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * Returns a set of 'true' and 'false' parameters for each of the setter/getter method pairs
-     *
      * @return array
      */
     public function dataProviderDirectSettersGettersMethods()
     {
-        return $this->_buildTrueFalsePairs(
-            [
-                [
-                    'setShippingPriceIncludeTax',
-                    'shippingPriceIncludesTax'
-                ],
-                [
-                    'setNeedUseShippingExcludeTax',
-                    'getNeedUseShippingExcludeTax'
-                ],
-                [
-                    'setPriceIncludesTax',
-                    'priceIncludesTax'
-                ]
-            ]
-        );
+        return [
+            ['setShippingPriceIncludeTax', 'shippingPriceIncludesTax', true],
+            ['setShippingPriceIncludeTax', 'shippingPriceIncludesTax', false],
+            ['setNeedUseShippingExcludeTax', 'getNeedUseShippingExcludeTax', true],
+            ['setNeedUseShippingExcludeTax', 'getNeedUseShippingExcludeTax', false],
+            ['setPriceIncludesTax', 'priceIncludesTax', true],
+            ['setPriceIncludesTax', 'priceIncludesTax', false],
+            ['setPriceIncludesTax', 'priceIncludesTax', null]
+        ];
     }
 
-    /**
-     * Returns an output array that is twice the size of the input array by adding 'true' and then 'false' to the
-     * set of parameters given
-     *
-     * @param array $arrayIn
-     * @return array
-     */
-    protected function _buildTrueFalsePairs($arrayIn)
-    {
-        $arrayOut = [];
-
-        foreach ($arrayIn as $paramArray) {
-            // replicate the paramArray, append 'true', and add the new array to the output array
-            $arrayT = $paramArray;
-            $arrayT[] = true;
-            $arrayOut[] = $arrayT;
-            // replicate the paramArray, append 'false', and add the new array to the output array
-            $arrayF = $paramArray;
-            $arrayF[] = false;
-            $arrayOut[] = $arrayF;
-        }
-
-        return $arrayOut;
-    }
-
-
     /**
      * Tests the getCalculationSequence method
      *
@@ -399,6 +362,24 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
                 Config::CONFIG_XML_PATH_CROSS_BORDER_TRADE_ENABLED,
                 true,
                 true
+            ],
+            [
+                'isWrongDisplaySettingsIgnored',
+                Config::XML_PATH_TAX_NOTIFICATION_IGNORE_PRICE_DISPLAY,
+                true,
+                true
+            ],
+            [
+                'isWrongDiscountSettingsIgnored',
+                Config::XML_PATH_TAX_NOTIFICATION_IGNORE_DISCOUNT,
+                true,
+                true
+            ],
+            [
+                'getInfoUrl',
+                Config::XML_PATH_TAX_NOTIFICATION_INFO_URL,
+                true,
+                true
             ]
         ];
     }
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/Sales/Total/Quote/TaxTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/Sales/Total/Quote/TaxTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1b13b62cf29575e886aab8d3111b3f16329ef431
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/Sales/Total/Quote/TaxTest.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Model\Sales\Total\Quote;
+
+/**
+ * Test class for \Magento\Tax\Model\Sales\Total\Quote\Tax
+ */
+use Magento\Tax\Model\Calculation;
+
+class TaxTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Tests the specific method
+     *
+     * @param string $calculationSequence
+     * @param string $keyExpected
+     * @param string $keyAbsent
+     * @dataProvider dataProviderProcessConfigArray
+     */
+    public function testProcessConfigArray($calculationSequence, $keyExpected, $keyAbsent)
+    {
+        $taxData = $this->getMock('Magento\Tax\Helper\Data', [], [], '', false);
+        $taxData
+            ->expects($this->any())
+            ->method('getCalculationSequence')
+            ->will($this->returnValue($calculationSequence));
+
+        $config = $this->getMock('\Magento\Tax\Model\Config', [], [], '', false);
+        $taxCalculationService = $this->getMock('\Magento\Tax\Service\V1\TaxCalculationService', [], [], '', false);
+        $quoteDetailsBuilder = $this->getMock('\Magento\Tax\Service\V1\Data\QuoteDetailsBuilder', [], [], '', false);
+
+        /** @var \Magento\Tax\Model\Sales\Total\Quote\Tax */
+        $taxTotalsCalcModel = new Tax($taxData, $config, $taxCalculationService, $quoteDetailsBuilder);
+        $array = $taxTotalsCalcModel->processConfigArray([], null);
+        $this->assertArrayHasKey($keyExpected, $array, 'Did not find the expected array key: ' . $keyExpected);
+        $this->assertArrayNotHasKey($keyAbsent, $array, 'Should not have found the array key; ' . $keyAbsent);
+    }
+
+    /**
+     * @return array
+     */
+    public function dataProviderProcessConfigArray()
+    {
+        return [
+            [Calculation::CALC_TAX_BEFORE_DISCOUNT_ON_INCL, 'before', 'after'],
+            [Calculation::CALC_TAX_BEFORE_DISCOUNT_ON_EXCL, 'after', 'before'],
+            [Calculation::CALC_TAX_AFTER_DISCOUNT_ON_EXCL, 'after', 'before'],
+            [Calculation::CALC_TAX_AFTER_DISCOUNT_ON_INCL, 'after', 'before']
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/ProductTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/ProductTest.php
index fd5ea72fb4738e9a278457926bc943ae96d7e6b4..0e03cc3c019a9d7dff5080747d499150ea3da6db 100644
--- a/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/ProductTest.php
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/ProductTest.php
@@ -38,7 +38,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
         $this->_model = $objectManager->getObject('Magento\Tax\Model\TaxClass\Source\Product');
     }
 
-    public function testGetFlatColums()
+    public function testGetFlatColumns()
     {
         $abstractAttributeMock = $this->getMock(
             '\Magento\Eav\Model\Entity\Attribute\AbstractAttribute',
@@ -52,17 +52,17 @@ class ProductTest extends \PHPUnit_Framework_TestCase
 
         $this->_model->setAttribute($abstractAttributeMock);
 
-        $flatColums = $this->_model->getFlatColums();
+        $flatColumns = $this->_model->getFlatColumns();
 
-        $this->assertTrue(is_array($flatColums), 'FlatColums must be an array value');
-        $this->assertTrue(!empty($flatColums), 'FlatColums must be not empty');
-        foreach ($flatColums as $result) {
-            $this->assertArrayHasKey('unsigned', $result, 'FlatColums must have "unsigned" column');
-            $this->assertArrayHasKey('default', $result, 'FlatColums must have "default" column');
-            $this->assertArrayHasKey('extra', $result, 'FlatColums must have "extra" column');
-            $this->assertArrayHasKey('type', $result, 'FlatColums must have "type" column');
-            $this->assertArrayHasKey('nullable', $result, 'FlatColums must have "nullable" column');
-            $this->assertArrayHasKey('comment', $result, 'FlatColums must have "comment" column');
+        $this->assertTrue(is_array($flatColumns), 'FlatColumns must be an array value');
+        $this->assertTrue(!empty($flatColumns), 'FlatColumns must be not empty');
+        foreach ($flatColumns as $result) {
+            $this->assertArrayHasKey('unsigned', $result, 'FlatColumns must have "unsigned" column');
+            $this->assertArrayHasKey('default', $result, 'FlatColumns must have "default" column');
+            $this->assertArrayHasKey('extra', $result, 'FlatColumns must have "extra" column');
+            $this->assertArrayHasKey('type', $result, 'FlatColumns must have "type" column');
+            $this->assertArrayHasKey('nullable', $result, 'FlatColumns must have "nullable" column');
+            $this->assertArrayHasKey('comment', $result, 'FlatColumns must have "comment" column');
         }
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Pricing/Price/Plugin/AttributePriceTest.php b/dev/tests/unit/testsuite/Magento/Tax/Pricing/Price/Plugin/AttributePriceTest.php
index 9e9e3bd4c9aa5c05c912d7816a95bd77daf1ff7c..a19f769154c3fc600c506fb4f41a547d12dcb175 100644
--- a/dev/tests/unit/testsuite/Magento/Tax/Pricing/Price/Plugin/AttributePriceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Tax/Pricing/Price/Plugin/AttributePriceTest.php
@@ -33,8 +33,8 @@ class AttributePriceTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Tax\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */
     protected $taxHelperMock;
 
-    /** @var \Magento\Tax\Model\Calculation|\PHPUnit_Framework_MockObject_MockObject */
-    protected $calculationMock;
+    /** @var \Magento\Tax\Service\V1\TaxCalculationServiceInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $calculationServiceMock;
 
     /** @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject */
     protected $productMock;
@@ -67,9 +67,9 @@ class AttributePriceTest extends \PHPUnit_Framework_TestCase
             false,
             false
         );
-        $this->calculationMock = $this->getMock(
-            'Magento\Tax\Model\Calculation',
-            ['getRate', 'getRateRequest', '__wakeup'],
+        $this->calculationServiceMock = $this->getMock(
+            'Magento\Tax\Service\V1\TaxCalculationService',
+            ['getDefaultCalculatedRate', 'getCalculatedRate'],
             [],
             '',
             false,
@@ -118,7 +118,7 @@ class AttributePriceTest extends \PHPUnit_Framework_TestCase
 
         $this->plugin = new \Magento\Tax\Pricing\Price\Plugin\AttributePrice(
             $this->taxHelperMock,
-            $this->calculationMock
+            $this->calculationServiceMock
         );
 
 
@@ -132,12 +132,13 @@ class AttributePriceTest extends \PHPUnit_Framework_TestCase
         $this->productMock->expects($this->once())
             ->method('getTaxClassId')
             ->will($this->returnValue('tax-class-id'));
-        $this->calculationMock->expects($this->exactly(2))
-            ->method('getRateRequest')
-            ->will($this->returnValue($this->rateRequestMock));
-        $this->calculationMock->expects($this->exactly(2))
-            ->method('getRate')
-            ->with($this->equalTo($this->rateRequestMock))
+        $this->calculationServiceMock->expects($this->once())
+            ->method('getDefaultCalculatedRate')
+            ->with('tax-class-id', 1)
+            ->will($this->returnValue(99.10));
+        $this->calculationServiceMock->expects($this->once())
+            ->method('getCalculatedRate')
+            ->with('tax-class-id', 1)
             ->will($this->returnValue(99.10));
         $this->productMock->expects($this->once())
             ->method('getPriceInfo')
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxCalculationServiceTest.php b/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxCalculationServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b13cd650e6f034cc0f52c1b1fd14e196e429bf69
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxCalculationServiceTest.php
@@ -0,0 +1,419 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1;
+
+use Magento\Tax\Service\V1\Data\QuoteDetails\Item as QuoteDetailsItem;
+use Magento\TestFramework\Helper\ObjectManager;
+
+/**
+ * Test TaxCalculationService
+ */
+class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
+{
+    const TAX = 0.1;
+
+    /** @var \Magento\Tax\Service\V1\TaxCalculationService */
+    private $taxCalculationService;
+
+    /** @var \Magento\Tax\Service\V1\Data\QuoteDetailsBuilder */
+    private $quoteDetailsBuilder;
+
+    /** @var  \Magento\Tax\Service\V1\Data\TaxDetails\ItemBuilder*/
+    private $taxDetailsItemBuilder;
+
+    /** @var \Magento\Tax\Service\V1\Data\TaxDetailsBuilder */
+    private $taxDetailsBuilder;
+
+    /** @var  \PHPUnit_Framework_MockObject_MockObject|\Magento\Store\Model\StoreManagerInterface */
+    private $storeManager;
+
+    /** @var  \PHPUnit_Framework_MockObject_MockObject|\Magento\Tax\Model\Calculation\CalculatorFactory */
+    private $calculatorFactory;
+
+    public function setUp()
+    {
+        $objectManager = new ObjectManager($this);
+        $this->quoteDetailsBuilder = $objectManager->getObject('Magento\Tax\Service\V1\Data\QuoteDetailsBuilder');
+        $this->storeManager = $this->getMockBuilder('Magento\Store\Model\StoreManagerInterface')
+            ->disableOriginalConstructor()->getMock();
+        $this->calculatorFactory = $this->getMockBuilder('Magento\Tax\Model\Calculation\CalculatorFactory')
+            ->disableOriginalConstructor()->getMock();
+        $calculationTool = $this->getMockBuilder('Magento\Tax\Model\Calculation')
+            ->disableOriginalConstructor()->getMock();
+        $calculationTool->expects($this->any())
+            ->method('round')
+            ->will($this->returnArgument(0));
+        $this->taxDetailsBuilder = $objectManager->getObject('Magento\Tax\Service\V1\Data\TaxDetailsBuilder');
+        $this->taxDetailsItemBuilder = $objectManager->getObject('Magento\Tax\Service\V1\Data\TaxDetails\ItemBuilder');
+        $this->taxCalculationService = $objectManager->getObject(
+            'Magento\Tax\Service\V1\TaxCalculationService',
+            [
+                'calculation' => $calculationTool,
+                'calculatorFactory' => $this->calculatorFactory,
+                'taxDetailsBuilder' => $this->taxDetailsBuilder,
+                'taxDetailsItemBuilder' => $this->taxDetailsItemBuilder,
+                'storeManager' => $this->storeManager,
+            ]
+        );
+    }
+
+    /**
+     * @param array $quoteDetailsData
+     * @param array $taxDetailsData
+     * @param string $calculateCallback Name of a function within this test class which will be executed to create
+     *      a tax details item.
+     * @return void
+     * @dataProvider calculateTaxProvider
+     */
+    public function testCalculateTax($quoteDetailsData, $taxDetailsData, $calculateCallback = 'createTaxDetailsItem')
+    {
+        $storeMock = $this->getMockBuilder('Magento\Store\Model\Store')->disableOriginalConstructor()->getMock();
+        $this->storeManager->expects($this->any())
+            ->method('getStore')
+            ->will($this->returnValue($storeMock));
+        $calculatorMock = $this->getMockBuilder('\Magento\Tax\Model\Calculation\AbstractCalculator')
+            ->disableOriginalConstructor()->setMethods(['calculate'])->getMockForAbstractClass();
+        $this->calculatorFactory->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($calculatorMock));
+        $calculatorMock->expects($this->any())
+            ->method('calculate')
+            ->will($this->returnCallback([$this, $calculateCallback]));
+
+        $quoteDetails = $this->quoteDetailsBuilder->populateWithArray($quoteDetailsData)->create();
+
+        $taxDetails = $this->taxCalculationService->calculateTax($quoteDetails);
+
+        $this->assertEquals($taxDetailsData, $taxDetails->__toArray());
+    }
+
+    /**
+     * @return array
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function calculateTaxProvider()
+    {
+        return [
+            'empty' => [
+                'quoteDetails' => [],
+                'taxDetails' => [
+                    'subtotal' => 0,
+                    'tax_amount' => 0,
+                    'discount_tax_compensation_amount' => 0,
+                    'applied_taxes' => [],
+                    'items' => [],
+                ],
+            ],
+            'one_item' => [
+                'quoteDetails' => [
+                    'billing_address' => [
+                        'postcode' => '55555',
+                        'country_id' => 'US',
+                        'region' => ['region_id' => 42],
+                    ],
+                    'shipping_address' => [
+                        'postcode' => '55555',
+                        'country_id' => 'US',
+                        'region' => ['region_id' => 42],
+                    ],
+                    'customer_tax_class_id' => 'DefaultCustomerClass',
+                    'items' => [
+                        [
+                            'code' => 'sku_1',
+                            'type' => 'product',
+                            'quantity' => 10,
+                            'unit_price' => 1,
+                            'tax_class_id' => 'DefaultProductClass',
+                        ]
+                    ],
+                ],
+                'taxDetails' => [
+                    'subtotal' => 10,
+                    'tax_amount' => 1,
+                    'discount_tax_compensation_amount' => 0,
+                    'applied_taxes' => [],
+                    'items' => [
+                        'sku_1' => [
+                            'code' => 'sku_1',
+                            'type' => 'product',
+                            'price' => 1,
+                            'row_total' => 10,
+                            'tax_percent' => self::TAX,
+                            'row_tax' => 1,
+                            'row_total_incl_tax' => 11,
+                            'price_incl_tax' => 1.1,
+                        ]
+                    ],
+                ],
+            ], // End one_item
+            'empty_applied' => [
+                'quoteDetails' => [],
+                'taxDetails' => [
+                    'subtotal' => 0,
+                    'tax_amount' => 0,
+                    'discount_tax_compensation_amount' => 0,
+                    'applied_taxes' => [],
+                    'items' => [],
+                ],
+                'calculateCallbacks' => 'createTaxDetailsItemWithAppliedTaxes',
+            ], // End empty_applied
+            'one_item_applied' => [
+                'quoteDetails' => [
+                    'billing_address' => [
+                        'postcode' => '55555',
+                        'country_id' => 'US',
+                        'region' => ['region_id' => 42],
+                    ],
+                    'shipping_address' => [
+                        'postcode' => '55555',
+                        'country_id' => 'US',
+                        'region' => ['region_id' => 42],
+                    ],
+                    'customer_tax_class_id' => 'DefaultCustomerClass',
+                    'items' => [
+                        [
+                            'code' => 'sku_1',
+                            'type' => 'product',
+                            'quantity' => 10,
+                            'unit_price' => 1,
+                            'tax_class_id' => 'DefaultProductClass',
+                        ]
+                    ],
+                ],
+                'taxDetails' => [
+                    'subtotal' => 10,
+                    'tax_amount' => 1,
+                    'discount_tax_compensation_amount' => 0,
+                    'applied_taxes' => [
+                        [
+                            'amount' => 0.1,
+                            'percent' => self::TAX,
+                            'rates' => [
+                                [
+                                    'code' => 'TAX',
+                                    'title' => 'Tax',
+                                    'percent' => self::TAX,
+                                ]
+                            ],
+                            'tax_rate_key' => 'TAX_RATE',
+                        ]
+                    ],
+                    'items' => [
+                        'sku_1' => [
+                            'code' => 'sku_1',
+                            'type' => 'product',
+                            'price' => 1,
+                            'row_total' => 10,
+                            'tax_percent' => self::TAX,
+                            'row_tax' => 1,
+                            'row_total_incl_tax' => 11,
+                            'price_incl_tax' => 1.1,
+                            'applied_taxes' => [
+                                [
+                                    'amount' => 0.1,
+                                    'percent' => self::TAX,
+                                    'rates' => [
+                                        [
+                                            'code' => 'TAX',
+                                            'title' => 'Tax',
+                                            'percent' => self::TAX,
+                                        ]
+                                    ],
+                                    'tax_rate_key' => 'TAX_RATE',
+                                ]
+                            ],
+                        ]
+                    ],
+                ],
+                'calculateCallbacks' => 'createTaxDetailsItemWithAppliedTaxes',
+            ], // End one_item_applied
+            'bundled_items_applied' => [
+                'quoteDetails' => [
+                    'billing_address' => [
+                        'postcode' => '55555',
+                        'country_id' => 'US',
+                        'region' => ['region_id' => 42],
+                    ],
+                    'shipping_address' => [
+                        'postcode' => '55555',
+                        'country_id' => 'US',
+                        'region' => ['region_id' => 42],
+                    ],
+                    'customer_tax_class_id' => 'DefaultCustomerClass',
+                    'items' => [
+                        [
+                            'code' => 'sku_1',
+                            'type' => 'product',
+                            'quantity' => 10,
+                            'unit_price' => 1,
+                            'tax_class_id' => 'DefaultProductClass',
+                            'parent_code' => 'bundle',
+                        ],
+                        [
+                            'code' => 'sku_2',
+                            'type' => 'product',
+                            'quantity' => 1,
+                            'unit_price' => 10,
+                            'tax_class_id' => 'DefaultProductClass',
+                            'parent_code' => 'bundle',
+                        ],
+                        [
+                            'code' => 'bundle',
+                            'type' => 'product',
+                            'quantity' => 2,
+                            'unit_price' => 0,
+                            'tax_class_id' => 'DefaultProductClass',
+                        ],
+                    ],
+                ],
+                'taxDetails' => [
+                    'subtotal' => 20,
+                    'tax_amount' => 2,
+                    'discount_tax_compensation_amount' => 0,
+                    'applied_taxes' => [
+                        [
+                            'amount' => 1.1,
+                            'percent' => self::TAX,
+                            'rates' => [
+                                [
+                                    'code' => 'TAX',
+                                    'title' => 'Tax',
+                                    'percent' => self::TAX,
+                                ]
+                            ],
+                            'tax_rate_key' => 'TAX_RATE',
+                        ]
+                    ],
+                    'items' => [
+                        'sku_1' => [
+                            'code' => 'sku_1',
+                            'type' => 'product',
+                            'price' => 1,
+                            'row_total' => 10,
+                            'tax_percent' => self::TAX,
+                            'row_tax' => 1,
+                            'row_total_incl_tax' => 11,
+                            'price_incl_tax' => 1.1,
+                            'applied_taxes' => [
+                                [
+                                    'amount' => 0.1,
+                                    'percent' => self::TAX,
+                                    'rates' => [
+                                        [
+                                            'code' => 'TAX',
+                                            'title' => 'Tax',
+                                            'percent' => self::TAX,
+                                        ]
+                                    ],
+                                    'tax_rate_key' => 'TAX_RATE',
+                                ]
+                            ],
+                        ],
+                        'sku_2' => [
+                            'code' => 'sku_2',
+                            'type' => 'product',
+                            'price' => 10,
+                            'row_total' => 10,
+                            'tax_percent' => self::TAX,
+                            'row_tax' => 1,
+                            'row_total_incl_tax' => 11,
+                            'price_incl_tax' => 11,
+                            'applied_taxes' => [
+                                [
+                                    'amount' => 1,
+                                    'percent' => self::TAX,
+                                    'rates' => [
+                                        [
+                                            'code' => 'TAX',
+                                            'title' => 'Tax',
+                                            'percent' => self::TAX,
+                                        ]
+                                    ],
+                                    'tax_rate_key' => 'TAX_RATE',
+                                ]
+                            ],
+                        ],
+                        'bundle' => [
+                            'price' => 10,
+                            'price_incl_tax' => 11,
+                            'row_total' => 20,
+                            'row_total_incl_tax' => 22,
+                            'row_tax' => 2,
+                            'code' => 'bundle',
+                            'type' => 'product',
+                        ],
+                    ],
+                ],
+                'calculateCallbacks' => 'createTaxDetailsItemWithAppliedTaxes',
+            ], // End bundled_items_applied
+        ];
+    }
+
+    /**
+     * Callback function that creates a tax details item from a quote details item for testing.
+     *
+     * @param QuoteDetailsItem $item
+     * @return Data\TaxDetails\Item
+     */
+    public function createTaxDetailsItem(QuoteDetailsItem $item)
+    {
+        $rowTotal = $item->getUnitPrice() * $item->getQuantity();
+        $rowTax = $rowTotal * self::TAX;
+        return $this->taxDetailsItemBuilder->populateWithArray($item->__toArray())
+            ->setPrice($item->getUnitPrice())
+            ->setRowTotal($rowTotal)
+            ->setTaxPercent(self::TAX)
+            ->setRowTax($rowTax)
+            ->setRowTotalInclTax($rowTotal + $rowTax)
+            ->setPriceInclTax($item->getUnitPrice() + ($item->getUnitPrice() * self::TAX))
+            ->create();
+    }
+
+    /**
+     * Callback function that creates a tax details item with applied taxes from a quote details item for testing.
+     *
+     * @param QuoteDetailsItem $item
+     * @return Data\TaxDetails\Item
+     */
+    public function createTaxDetailsItemWithAppliedTaxes(QuoteDetailsItem $item)
+    {
+        $appliedTaxRateBuilder = $this->taxDetailsBuilder->getAppliedTaxBuilder();
+        $taxRateBuilder = $appliedTaxRateBuilder->getAppliedTaxRateBuilder();
+        $rate = $taxRateBuilder
+            ->setPercent(self::TAX)
+            ->setCode('TAX')
+            ->setTitle('Tax')
+            ->create();
+        $appliedTaxes = $appliedTaxRateBuilder
+            ->setAmount($item->getUnitPrice() * self::TAX)
+            ->setTaxRateKey('TAX_RATE')
+            ->setPercent(self::TAX)
+            ->setRates([$rate])
+            ->create();
+        return $this->taxDetailsItemBuilder->populate($this->createTaxDetailsItem($item))
+            ->setAppliedTaxes([$appliedTaxes])
+            ->create();
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxClassServiceTest.php b/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxClassServiceTest.php
index 654619dbf083b25af70704eabcbff26e90973dc3..b988bdefdfa56e6c8645f65729fea1b2ccde1c53 100644
--- a/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxClassServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxClassServiceTest.php
@@ -27,6 +27,7 @@ namespace Magento\Tax\Service\V1;
 use Magento\Framework\Exception\InputException;
 use Magento\Tax\Service\V1\Data\TaxClass;
 use Magento\Tax\Service\V1\Data\TaxClassBuilder;
+use Magento\Tax\Service\V1\Data\TaxClassKey;
 
 /**
  * Test for \Magento\Tax\Service\V1\TaxClassService
@@ -35,6 +36,8 @@ use Magento\Tax\Service\V1\Data\TaxClassBuilder;
  */
 class TaxClassServiceTest extends \PHPUnit_Framework_TestCase
 {
+    const TAX_CLASS_ID = 'tax_class_id';
+    const TAX_CLASS_NAME = 'tax_class_name';
     /**
      * @var \Magento\Tax\Model\Resource\TaxClass\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
      */
@@ -45,6 +48,11 @@ class TaxClassServiceTest extends \PHPUnit_Framework_TestCase
      */
     private $searchResultBuilder;
 
+    /**
+     * @var \Magento\Framework\Service\V1\Data\SearchCriteriaBuilder|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $searchCriteriaBuilderMock;
+
     /**
      * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Tax\Model\ClassModelFactory
      */
@@ -376,31 +384,19 @@ class TaxClassServiceTest extends \PHPUnit_Framework_TestCase
 
     public function testSearch()
     {
-        $collectionSize = 3;
-        $currentPage = 1;
-        $pageSize = 10;
         $searchCriteria = $this->createSearchCriteria();
         $this->searchResultBuilder->expects($this->once())->method('setSearchCriteria')->with($searchCriteria);
-        /** @var \PHPUnit_Framework_MockObject_MockObject $collectionMock */
-        $collectionMock = $this->getMockBuilder('Magento\Tax\Model\Resource\TaxClass\Collection')
+
+        /** @var \PHPUnit_Framework_MockObject_MockObject $taxClassModelMock */
+        $taxClassModelMock = $this->getMockBuilder('Magento\Tax\Model\ClassModel')
             ->disableOriginalConstructor()
-            ->setMethods(['addFieldToFilter', 'getSize', 'setCurPage', 'setPageSize', 'getItems', 'addOrder'])
             ->getMock();
+        $collectionMock = $this->mockTaxClassCollection($taxClassModelMock);
+
         $this->taxClassCollectionFactory
             ->expects($this->once())
             ->method('create')
             ->will($this->returnValue($collectionMock));
-        $collectionMock->expects($this->exactly(2))->method('addFieldToFilter');
-        $collectionMock->expects($this->any())->method('getSize')->will($this->returnValue($collectionSize));
-        $collectionMock->expects($this->once())->method('setCurPage')->with($currentPage);
-        $collectionMock->expects($this->once())->method('setPageSize')->with($pageSize);
-        $collectionMock->expects($this->once())->method('addOrder')->with('class_name', 'ASC');
-
-        /** @var \PHPUnit_Framework_MockObject_MockObject $taxClassModelMock */
-        $taxClassModelMock = $this->getMockBuilder('Magento\Tax\Model\ClassModel')
-            ->disableOriginalConstructor()
-            ->getMock();
-        $collectionMock->expects($this->once())->method('getItems')->will($this->returnValue([$taxClassModelMock]));
         /** @var \PHPUnit_Framework_MockObject_MockObject $taxMock */
         $taxClassMock = $this->getMockBuilder('Magento\Tax\Service\V1\Data\TaxClass')
             ->disableOriginalConstructor()
@@ -418,6 +414,106 @@ class TaxClassServiceTest extends \PHPUnit_Framework_TestCase
         $this->taxClassService->searchTaxClass($searchCriteria);
     }
 
+    /**
+     * @param string $expected
+     * @param string[] $taxClassKeyMockValeMap
+     * @param bool $found
+     * @dataProvider getTaxClassIdDataProvider
+     */
+    public function testGetTaxClassId($expected, $taxClassKeyMockValeMap, $found = false)
+    {
+        /** @var \Magento\Tax\Service\V1\Data\TaxClassKey|\PHPUnit_Framework_MockObject_MockObject $taxClassKeyMock */
+        $taxClassKeyMock = $this->getMockBuilder('Magento\Tax\Service\V1\Data\TaxClassKey')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->mockReturnValue($taxClassKeyMock, $taxClassKeyMockValeMap);
+
+        if ($taxClassKeyMockValeMap['getType'] == TaxClassKey::TYPE_NAME) {
+            $this->searchCriteriaBuilderMock->expects($this->exactly(2))
+                ->method('addFilter')
+                ->will($this->returnValue($this->searchCriteriaBuilderMock));
+            /** @var \Magento\Framework\Service\V1\Data\SearchCriteria $searchCriteria*/
+            $searchCriteria = $this->createSearchCriteria();
+            $this->searchCriteriaBuilderMock->expects($this->once())
+                ->method('create')
+                ->will($this->returnValue($searchCriteria));
+            $this->searchResultBuilder->expects($this->once())->method('setSearchCriteria')->with($searchCriteria);
+
+            /** @var \PHPUnit_Framework_MockObject_MockObject $taxClassModelMock */
+            $taxClassModelMock = $this->getMockBuilder('Magento\Tax\Model\ClassModel')
+                ->disableOriginalConstructor()
+                ->getMock();
+            $collectionMock = $this->mockTaxClassCollection($taxClassModelMock);
+
+            $this->taxClassCollectionFactory
+                ->expects($this->once())
+                ->method('create')
+                ->will($this->returnValue($collectionMock));
+            /** @var \PHPUnit_Framework_MockObject_MockObject $taxMock */
+            $taxClassMock = $this->getMockBuilder('Magento\Tax\Service\V1\Data\TaxClass')
+                ->disableOriginalConstructor()
+                ->getMock();
+            $this->converterMock
+                ->expects($this->once())
+                ->method('createTaxClassData')
+                ->with($taxClassModelMock)
+                ->will($this->returnValue($taxClassMock));
+            $this->searchResultBuilder
+                ->expects($this->once())
+                ->method('setItems')
+                ->will($this->returnValue([$taxClassMock]));
+            $searchResultsMock = $this->getMockBuilder('Magento\Tax\Service\V1\Data\TaxClassSearchResults')
+                ->disableOriginalConstructor()
+                ->getMock();
+            $searchResultsMock->expects($this->once())
+                ->method('getItems')
+                ->will($this->returnValue($found ? [$taxClassMock] : []));
+            $taxClassMock->expects($this->any())
+                ->method('getClassId')
+                ->will($this->returnValue(self::TAX_CLASS_ID));
+            $this->searchResultBuilder
+                ->expects($this->once())
+                ->method('create')
+                ->will($this->returnValue($searchResultsMock));
+
+        }
+        $this->assertEquals($expected, $this->taxClassService->getTaxClassId($taxClassKeyMock));
+    }
+
+    public function testGetTaxClassIdEmptyTaxClassKey()
+    {
+        $this->assertNull($this->taxClassService->getTaxClassId(null));
+    }
+
+    public function getTaxClassIdDataProvider()
+    {
+        return [
+
+            'type_id' => [
+                self::TAX_CLASS_ID,
+                [
+                    'getType' => TaxClassKey::TYPE_ID,
+                    'getValue' => self::TAX_CLASS_ID,
+                ],
+            ],
+            'type_name_not_found' => [
+                null,
+                [
+                    'getType' => TaxClassKey::TYPE_NAME,
+                    'getValue' => self::TAX_CLASS_NAME,
+                ],
+            ],
+            'type_name_found' => [
+                self::TAX_CLASS_ID,
+                [
+                    'getType' => TaxClassKey::TYPE_NAME,
+                    'getValue' => self::TAX_CLASS_NAME,
+                ],
+                true,
+            ],
+        ];
+    }
+
     /**
      * @return TaxClassService
      */
@@ -439,9 +535,15 @@ class TaxClassServiceTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->getMock();
 
+        $this->searchCriteriaBuilderMock = $this->getMockBuilder(
+            'Magento\Framework\Service\V1\Data\SearchCriteriaBuilder'
+        )->disableOriginalConstructor()
+            ->getMock();
+
         $taxClassService = $this->objectManager->getObject(
             'Magento\Tax\Service\V1\TaxClassService',
             [
+                'searchCriteriaBuilder' => $this->searchCriteriaBuilderMock,
                 'taxClassCollectionFactory' => $this->taxClassCollectionFactory,
                 'classModelRegistry' => $this->classModelRegistryMock,
                 'searchResultsBuilder' => $this->searchResultBuilder,
@@ -497,4 +599,38 @@ class TaxClassServiceTest extends \PHPUnit_Framework_TestCase
             ->create();
         return $searchCriteria;
     }
+
+    /**
+     * @param $taxClassModelMock
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    private function mockTaxClassCollection($taxClassModelMock)
+    {
+        $collectionSize = 3;
+        $currentPage = 1;
+        $pageSize = 10;
+        /** @var \PHPUnit_Framework_MockObject_MockObject $collectionMock */
+        $collectionMock = $this->getMockBuilder('Magento\Tax\Model\Resource\TaxClass\Collection')
+            ->disableOriginalConstructor()
+            ->setMethods(['addFieldToFilter', 'getSize', 'setCurPage', 'setPageSize', 'getItems', 'addOrder'])
+            ->getMock();
+        $collectionMock->expects($this->exactly(2))->method('addFieldToFilter');
+        $collectionMock->expects($this->any())->method('getSize')->will($this->returnValue($collectionSize));
+        $collectionMock->expects($this->once())->method('setCurPage')->with($currentPage);
+        $collectionMock->expects($this->once())->method('setPageSize')->with($pageSize);
+        $collectionMock->expects($this->once())->method('addOrder')->with('class_name', 'ASC');
+        $collectionMock->expects($this->once())->method('getItems')->will($this->returnValue([$taxClassModelMock]));
+        return $collectionMock;
+    }
+
+    /**
+     * @param \PHPUnit_Framework_MockObject_MockObject $mock
+     * @param array $valueMap
+     */
+    private function mockReturnValue($mock, $valueMap)
+    {
+        foreach ($valueMap as $method => $value) {
+            $mock->expects($this->any())->method($method)->will($this->returnValue($value));
+        }
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php b/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php
index 66e4acd2ff73cd28af59c3e4df4a76c4520b4ae6..3f78f7a08df8a4d2abfa059889c987feb6ece04e 100644
--- a/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php
@@ -268,6 +268,7 @@ class TaxRateServiceTest extends \PHPUnit_Framework_TestCase
         $taxRate = $this->taxRateBuilder
             ->setId(2)
             ->setCode('Rate-Code')
+            ->setCountryId('US')
             ->setPercentageRate(0.1)
             ->setRegionId('TX')
             ->create();
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php b/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php
index 8e782df621e273e74f0a27e3e57ff74b52ba78fd..a72665c8cf884b51d7f33b0390a8cfaa93c1f407 100644
--- a/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php
@@ -26,9 +26,14 @@ namespace Magento\Tax\Service\V1;
 use Magento\Framework\Exception\ErrorMessage;
 use Magento\Framework\Exception\InputException;
 use Magento\Framework\Exception\NoSuchEntityException;
-use Magento\Framework\Model\Resource\Iterator;
+use Magento\Tax\Service\V1\Data\TaxRule;
 use Magento\TestFramework\Helper\ObjectManager;
 
+/**
+ * Class TaxRuleServiceTest
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
 class TaxRuleServiceTest extends \PHPUnit_Framework_TestCase
 {
     /**
@@ -56,6 +61,22 @@ class TaxRuleServiceTest extends \PHPUnit_Framework_TestCase
      */
     private $taxRuleModelFactoryMock;
 
+    /**
+     * @var \Magento\Framework\Service\V1\Data\FilterBuilder | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $filterBuilderMock;
+
+    /**
+     * @var \Magento\Framework\Service\V1\Data\SearchCriteriaBuilder | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $searchCriteriaBuilderMock;
+
+
+    /**
+     * @var \Magento\Tax\Service\V1\TaxRateServiceInterface | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $taxRateServiceMock;
+
     /**
      * @var ObjectManager
      */
@@ -84,15 +105,19 @@ class TaxRuleServiceTest extends \PHPUnit_Framework_TestCase
         $taxRuleResultsBuilder = $this->objectManager->getObject(
             'Magento\Tax\Service\V1\Data\TaxRuleSearchResultsBuilder'
         );
-        $this->taxRuleService = $this->objectManager->getObject(
-            'Magento\Tax\Service\V1\TaxRuleService',
-            [
-                'taxRuleRegistry'     => $this->ruleRegistryMock,
-                'converter'           => $this->converterMock,
-                'taxRuleModelFactory' => $this->taxRuleModelFactoryMock,
-                'taxRuleSearchResultsBuilder' => $taxRuleResultsBuilder
-            ]
-        );
+        $this->filterBuilderMock = $this->getMockBuilder('\Magento\Framework\Service\V1\Data\FilterBuilder')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->searchCriteriaBuilderMock = $this->getMockBuilder(
+            '\Magento\Framework\Service\V1\Data\SearchCriteriaBuilder'
+        )
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->taxRateServiceMock = $this->getMockBuilder('\Magento\Tax\Service\V1\TaxRateServiceInterface')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->taxRuleService = $this->getTaxRuleService($taxRuleResultsBuilder);
     }
 
     public function testDeleteTaxRule()
@@ -290,6 +315,8 @@ class TaxRuleServiceTest extends \PHPUnit_Framework_TestCase
             'empty fields' => [
                 [],
                 [
+                    'sort_order is a required field.',
+                    'priority is a required field.',
                     'code is a required field.',
                     'customer_tax_class_ids is a required field.',
                     'product_tax_class_ids is a required field.',
@@ -388,7 +415,7 @@ class TaxRuleServiceTest extends \PHPUnit_Framework_TestCase
             ->getMock();
         /** @var \Magento\Tax\Service\V1\Data\TaxRuleBuilder $taxRuleBuilder */
         $taxRuleBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\TaxRuleBuilder');
-        /** @var \Magento\Tax\Service\V1\Data\TaxRule $taxRule */
+        /** @var TaxRule $taxRule */
         $taxRule = $taxRuleBuilder->create();
 
         $taxRuleModel = $this->getMockBuilder('Magento\Tax\Model\Calculation\Rule')
@@ -441,4 +468,150 @@ class TaxRuleServiceTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals($expectedResults->getItems(), $actualResults->getItems());
         $this->assertSame($taxRule, $actualResults->getItems()[0]);
     }
+
+    /**
+     *
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function testGetRatesByCustomerAndProductTaxClassId()
+    {
+        $customerTaxClass = 0;
+        $productTaxClass = 0;
+
+        $filterOne = 'filter_one';
+        $filterTwo = 'filter_two';
+
+        /** @var \PHPUnit_Framework_MockObject_MockObject |
+         * \Magento\Tax\Model\Resource\Calculation\Rule\Collection $mockCollection */
+        $mockCollection = $this->getMockBuilder('\Magento\Tax\Model\Resource\Calculation\Rule\Collection')
+            ->disableOriginalConstructor()
+            ->setMethods(['__wakeup', 'getItems', 'getSize', 'addFieldToFilter', '_beforeLoad', 'getIterator'])
+            ->getMock();
+
+        $taxRuleModel = $this->getMockBuilder('Magento\Tax\Model\Calculation\Rule')
+            ->disableOriginalConstructor()->getMock();
+        $mockCollection->expects($this->once())
+            ->method('getIterator')
+            ->will($this->returnValue(new \ArrayIterator([$taxRuleModel])));
+        $mockCollection->expects($this->once())
+            ->method('getSize')
+            ->will($this->returnValue(1));
+
+        $this->ruleModelMock->expects($this->once())
+            ->method('getCollection')
+            ->will($this->returnValue($mockCollection));
+
+        $this->filterBuilderMock->expects($this->exactly(2))
+            ->method('setField')
+            ->with(
+                $this->logicalOr(
+                    $this->equalTo(TaxRule::CUSTOMER_TAX_CLASS_IDS),
+                    $this->equalTo(TaxRule::PRODUCT_TAX_CLASS_IDS)
+                )
+            )
+            ->will($this->returnSelf());
+
+        $this->filterBuilderMock->expects($this->exactly(2))
+            ->method('setValue')
+            ->with(
+                $this->logicalOr(
+                    $this->equalTo([$customerTaxClass]),
+                    $this->equalTo([$productTaxClass])
+                )
+            )
+            ->will($this->returnSelf());
+
+        $this->filterBuilderMock->expects($this->at(2))
+            ->method('create')
+            ->will($this->returnValue($filterOne));
+        $this->filterBuilderMock->expects($this->at(5))
+            ->method('create')
+            ->will($this->returnValue($filterTwo));
+
+        $this->searchCriteriaBuilderMock->expects($this->exactly(2))
+            ->method('addFilter')
+            ->with($this->logicalOr([$filterOne], [$filterTwo]))
+            ->will($this->returnSelf());
+
+        $searchCriteria = $this->getMockBuilder('\Magento\Framework\Service\V1\Data\SearchCriteria')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $mockFilters = $this->getMockBuilder('\Magento\Framework\Service\V1\Data\Filter')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $mockFilterGroups = $this->getMockBuilder('\Magento\Framework\Service\V1\Data\Search\FilterGroup')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $mockFilterGroups->expects($this->any())
+            ->method('getFilters')
+            ->will($this->returnValue([$mockFilters]));
+
+        $searchCriteria->expects($this->once())
+            ->method('getFilterGroups')
+            ->will($this->returnValue([$mockFilterGroups]));
+
+        $this->searchCriteriaBuilderMock->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($searchCriteria));
+
+        $searchResults = $this->getMockBuilder('\Magento\Tax\Service\V1\Data\TaxRuleSearchResults')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $taxRuleResultsBuilderMock= $this->getMockBuilder('Magento\Tax\Service\V1\Data\TaxRuleSearchResultsBuilder')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $mockTaxRule = $this->getMockBuilder('\Magento\Tax\Service\V1\Data\TaxRule')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $taxRules = [$mockTaxRule];
+
+        $searchResults->expects($this->once())
+            ->method('getItems')
+            ->will($this->returnValue($taxRules));
+
+        $mockTaxRule->expects($this->once())
+            ->method('getTaxRateIds')
+            ->will($this->returnValue([777]));
+
+        $this->taxRateServiceMock->expects($this->once())
+            ->method('getTaxRate')
+            ->with(777)
+            ->will($this->returnValue(888));
+
+        $taxRuleResultsBuilderMock->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($searchResults));
+
+        $taxRuleService = $this->getTaxRuleService($taxRuleResultsBuilderMock);
+        $this->assertSame(
+            [888],
+            $taxRuleService->getRatesByCustomerAndProductTaxClassId($customerTaxClass, $productTaxClass)
+        );
+    }
+
+    /**
+     * Get tax rule service
+     *
+     * @param $taxRuleResultsBuilder
+     * @return \Magento\Tax\Service\V1\TaxRuleService
+     */
+    private function getTaxRuleService($taxRuleResultsBuilder)
+    {
+        return $this->objectManager->getObject(
+            'Magento\Tax\Service\V1\TaxRuleService',
+            [
+                'taxRuleRegistry' => $this->ruleRegistryMock,
+                'converter' => $this->converterMock,
+                'taxRuleModelFactory' => $this->taxRuleModelFactoryMock,
+                'taxRuleSearchResultsBuilder' => $taxRuleResultsBuilder,
+                'filterBuilder' => $this->filterBuilderMock,
+                'taxRateService' => $this->taxRateServiceMock,
+                'searchCriteriaBuilder' => $this->searchCriteriaBuilderMock
+            ]
+        );
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Theme/Controller/Adminhtml/System/Design/Theme/SaveTest.php b/dev/tests/unit/testsuite/Magento/Theme/Controller/Adminhtml/System/Design/Theme/SaveTest.php
index 0c65499b8c3c760995baa3ae8215ca3b7a1801c3..56d3e8970cb82a445bfbfe806fb01d75ee04bab9 100644
--- a/dev/tests/unit/testsuite/Magento/Theme/Controller/Adminhtml/System/Design/Theme/SaveTest.php
+++ b/dev/tests/unit/testsuite/Magento/Theme/Controller/Adminhtml/System/Design/Theme/SaveTest.php
@@ -32,7 +32,6 @@ class SaveTest extends \Magento\Theme\Controller\Adminhtml\System\Design\ThemeTe
     protected $name = 'Save';
 
     /**
-     * @covers \Magento\Theme\Controller\Adminhtml\System\Design\Theme::saveAction
      * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
      */
     public function testSaveAction()
@@ -42,53 +41,31 @@ class SaveTest extends \Magento\Theme\Controller\Adminhtml\System\Design\ThemeTe
         $jsRemovedFiles = array(3, 4);
         $jsOrder = array(1 => '1', 2 => 'test');
 
-        $this->_request->expects(
-            $this->at(0)
-        )->method(
-                'getParam'
-            )->with(
-                'back',
-                false
-            )->will(
-                $this->returnValue(true)
-            );
+        $this->_request->expects($this->at(0))
+            ->method('getParam')
+            ->with('back', false)
+            ->will($this->returnValue(true));
+
+        $this->_request->expects($this->at(1))
+            ->method('getParam')
+            ->with('theme')
+            ->will($this->returnValue($themeData));
+
+        $this->_request->expects($this->at(2))
+            ->method('getParam')
+            ->with('custom_css_content')
+            ->will($this->returnValue($customCssContent));
+
+        $this->_request->expects($this->at(3))
+            ->method('getParam')
+            ->with('js_removed_files')
+            ->will($this->returnValue($jsRemovedFiles));
+
+        $this->_request->expects($this->at(4))
+            ->method('getParam')
+            ->with('js_order')
+            ->will($this->returnValue($jsOrder));
 
-        $this->_request->expects(
-            $this->at(1)
-        )->method(
-                'getParam'
-            )->with(
-                'theme'
-            )->will(
-                $this->returnValue($themeData)
-            );
-        $this->_request->expects(
-            $this->at(2)
-        )->method(
-                'getParam'
-            )->with(
-                'custom_css_content'
-            )->will(
-                $this->returnValue($customCssContent)
-            );
-        $this->_request->expects(
-            $this->at(3)
-        )->method(
-                'getParam'
-            )->with(
-                'js_removed_files'
-            )->will(
-                $this->returnValue($jsRemovedFiles)
-            );
-        $this->_request->expects(
-            $this->at(4)
-        )->method(
-                'getParam'
-            )->with(
-                'js_order'
-            )->will(
-                $this->returnValue($jsOrder)
-            );
         $this->_request->expects($this->once(5))->method('getPost')->will($this->returnValue(true));
 
         $themeMock = $this->getMock(
@@ -111,35 +88,20 @@ class SaveTest extends \Magento\Theme\Controller\Adminhtml\System\Design\ThemeTe
         );
         $themeFactory->expects($this->once())->method('create')->will($this->returnValue($themeMock));
 
-        $this->_objectManagerMock->expects(
-            $this->at(0)
-        )->method(
-                'get'
-            )->with(
-                'Magento\Framework\View\Design\Theme\FlyweightFactory'
-            )->will(
-                $this->returnValue($themeFactory)
-            );
+        $this->_objectManagerMock->expects($this->at(0))
+            ->method('get')
+            ->with('Magento\Framework\View\Design\Theme\FlyweightFactory')
+            ->will($this->returnValue($themeFactory));
 
-        $this->_objectManagerMock->expects(
-            $this->at(1)
-        )->method(
-                'get'
-            )->with(
-                'Magento\Theme\Model\Theme\Customization\File\CustomCss'
-            )->will(
-                $this->returnValue(null)
-            );
+        $this->_objectManagerMock->expects($this->at(1))
+            ->method('get')
+            ->with('Magento\Theme\Model\Theme\Customization\File\CustomCss')
+            ->will($this->returnValue(null));
 
-        $this->_objectManagerMock->expects(
-            $this->at(2)
-        )->method(
-                'create'
-            )->with(
-                'Magento\Theme\Model\Theme\SingleFile'
-            )->will(
-                $this->returnValue(null)
-            );
+        $this->_objectManagerMock->expects($this->at(2))
+            ->method('create')
+            ->with('Magento\Theme\Model\Theme\SingleFile')
+            ->will($this->returnValue(null));
 
         $this->_model->execute();
     }
diff --git a/dev/tests/unit/testsuite/Magento/UrlRedirect/Model/OptionProviderTest.php b/dev/tests/unit/testsuite/Magento/UrlRedirect/Model/OptionProviderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f58a6afd6a4fe97fcc4b6458c681b796137008de
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/UrlRedirect/Model/OptionProviderTest.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\UrlRedirect\Model;
+
+class OptionProviderTest extends \PHPUnit_Framework_TestCase
+{
+    public function testGetAllOptions()
+    {
+        $model = new OptionProvider();
+        $options = $model->getAllOptions();
+        $this->assertInternalType('array', $options);
+        $expectedOptions = array('' => 'No', 'R' => 'Temporary (302)', 'RP' => 'Permanent (301)');
+        $this->assertEquals($expectedOptions, $options);
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Webapi/Model/Soap/Wsdl/GeneratorTest.php b/dev/tests/unit/testsuite/Magento/Webapi/Model/Soap/Wsdl/GeneratorTest.php
index e52b1aa2b5f4b25382d9fa1f4ca4ac98841cd3b7..51316482330a193eb4a642bd68b9981f3aae84f0 100644
--- a/dev/tests/unit/testsuite/Magento/Webapi/Model/Soap/Wsdl/GeneratorTest.php
+++ b/dev/tests/unit/testsuite/Magento/Webapi/Model/Soap/Wsdl/GeneratorTest.php
@@ -42,6 +42,9 @@ class GeneratorTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Webapi\Model\Config\ClassReflector\TypeProcessor|\PHPUnit_Framework_MockObject_MockObject */
     protected $_typeProcessor;
 
+    /** @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $storeManagerMock;
+
     protected function setUp()
     {
         $this->_soapConfigMock = $this->getMockBuilder(
@@ -87,11 +90,32 @@ class GeneratorTest extends \PHPUnit_Framework_TestCase
             false
         );
 
-        $this->_wsdlGenerator = new \Magento\Webapi\Model\Soap\Wsdl\Generator(
-            $this->_soapConfigMock,
-            $this->_wsdlFactoryMock,
-            $this->_cacheMock,
-            $this->_typeProcessor
+        $this->storeManagerMock = $this->getMockBuilder(
+            'Magento\Store\Model\StoreManagerInterface'
+        )->setMethods(['getStore'])->disableOriginalConstructor()->getMockForAbstractClass();
+
+        $storeMock = $this->getMockBuilder(
+            'Magento\Store\Model\Store'
+        )->setMethods(['getCode', '__wakeup'])->disableOriginalConstructor()->getMock();
+
+        $this->storeManagerMock->expects($this->any())
+            ->method('getStore')
+            ->will($this->returnValue($storeMock));
+
+        $storeMock->expects($this->any())
+            ->method('getCode')
+            ->will($this->returnValue('store_code'));
+
+        $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->_wsdlGenerator = $helper->getObject(
+            'Magento\Webapi\Model\Soap\Wsdl\Generator',
+            [
+                'apiConfig' => $this->_soapConfigMock,
+                'wsdlFactory' => $this->_wsdlFactoryMock,
+                'cache' => $this->_cacheMock,
+                'typeProcessor' => $this->_typeProcessor,
+                'storeManagerMock' => $this->storeManagerMock
+            ]
         );
 
         parent::setUp();
@@ -178,7 +202,13 @@ class GeneratorTest extends \PHPUnit_Framework_TestCase
         )->setMethods(
             array('_collectCallInfo')
         )->setConstructorArgs(
-            array($this->_soapConfigMock, $this->_wsdlFactoryMock, $this->_cacheMock, $this->_typeProcessor)
+            [
+                $this->_soapConfigMock,
+                $this->_wsdlFactoryMock,
+                $this->_cacheMock,
+                $this->_typeProcessor,
+                $this->storeManagerMock
+            ]
         )->getMock();
 
         $wsdlGeneratorMock->expects(
diff --git a/dev/tests/unit/testsuite/Magento/Weee/Model/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Weee/Model/ConfigTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..03952de7d815bc90607d33634ef5ee3ba17b4176
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Weee/Model/ConfigTest.php
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/**
+ * Test class for \Magento\Weee\Model\Config
+ */
+namespace Magento\Weee\Model;
+
+class ConfigTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Tests the methods that rely on the ScopeConfigInterface object to provide their return values
+     *
+     * @param string $method
+     * @param string $path
+     * @param bool $configValue
+     * @param bool $expectedValue
+     * @dataProvider dataProviderScopeConfigMethods
+     */
+    public function testScopeConfigMethods($method, $path, $configValue, $expectedValue)
+    {
+        $scopeConfigMock = $this->getMockForAbstractClass('Magento\Framework\App\Config\ScopeConfigInterface');
+        $scopeConfigMock->expects($this->any())
+            ->method('getValue')
+            ->with($path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, null)
+            ->will($this->returnValue($configValue));
+        $scopeConfigMock->expects($this->any())
+            ->method('isSetFlag')
+            ->with($path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, null)
+            ->will($this->returnValue($configValue));
+
+        $taxData = $this->getMock('Magento\Tax\Helper\Data', [], [], '', false);
+
+        /** @var \Magento\Weee\Model\Config */
+        $model = new Config($scopeConfigMock, $taxData);
+        $this->assertEquals($expectedValue, $model->{$method}());
+    }
+
+    /**
+     * @return array
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function dataProviderScopeConfigMethods()
+    {
+        return [
+            [
+                'getPriceDisplayType',
+                Config::XML_PATH_FPT_DISPLAY_PRODUCT_VIEW,
+                true,
+                true
+            ],
+            [
+                'getListPriceDisplayType',
+                Config::XML_PATH_FPT_DISPLAY_PRODUCT_LIST,
+                true,
+                true
+            ],
+            [
+                'getSalesPriceDisplayType',
+                Config::XML_PATH_FPT_DISPLAY_SALES,
+                true,
+                true
+            ],
+            [
+                'getEmailPriceDisplayType',
+                Config::XML_PATH_FPT_DISPLAY_EMAIL,
+                true,
+                true
+            ],
+            [
+                'includeInSubtotal',
+                Config::XML_PATH_FPT_INCLUDE_IN_SUBTOTAL,
+                true,
+                true
+            ],
+            [
+                'isDiscounted',
+                Config::XML_PATH_FPT_DISCOUNTED,
+                true,
+                true
+            ],
+            [
+                'isTaxable',
+                Config::XML_PATH_FPT_TAXABLE,
+                true,
+                true
+            ],
+            [
+                'isEnabled',
+                Config::XML_PATH_FPT_ENABLED,
+                true,
+                true
+            ]
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Weee/Model/Total/Quote/WeeeTaxTest.php b/dev/tests/unit/testsuite/Magento/Weee/Model/Total/Quote/WeeeTaxTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b848ef344a900fc493f5eb69f6cf9298aaf4a40b
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Weee/Model/Total/Quote/WeeeTaxTest.php
@@ -0,0 +1,598 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Weee\Model\Total\Quote;
+
+use Magento\Tax\Model\Calculation;
+use Magento\Tax\Model\Sales\Total\Quote\CommonTaxCollector as CTC;
+
+class WeeeTaxTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Setup tax helper with an array of methodName, returnValue
+     *
+     * @param array $taxConfig
+     * @return \PHPUnit_Framework_MockObject_MockObject|\Magento\Tax\Helper\Data
+     */
+    protected function setupTaxHelper($taxConfig)
+    {
+        $taxHelper = $this->getMock('Magento\Tax\Helper\Data', [], [], '', false);
+
+        foreach ($taxConfig as $method => $value) {
+            $taxHelper->expects($this->any())->method($method)->will($this->returnValue($value));
+        }
+
+        return $taxHelper;
+    }
+
+    /**
+     * Setup calculator to return tax rates
+     *
+     * @param array $taxRates
+     * @return \PHPUnit_Framework_MockObject_MockObject|\Magento\Tax\Model\Calculation
+     */
+    protected function setupTaxCalculation($taxRates)
+    {
+        $storeTaxRate = $taxRates['store_tax_rate'];
+        $customerTaxRate = $taxRates['customer_tax_rate'];
+
+        $taxCalculation = $this->getMock('Magento\Tax\Model\Calculation', [], [], '', false);
+
+        $rateRequest = new \Magento\Framework\Object();
+        $defaultRateRequest = new \Magento\Framework\Object();
+
+        $taxCalculation->expects($this->any())->method('getRateRequest')->will($this->returnValue($rateRequest));
+        $taxCalculation
+            ->expects($this->any())
+            ->method('getRateOriginRequest')
+            ->will($this->returnValue($defaultRateRequest));
+
+        $taxCalculation
+            ->expects($this->any())
+            ->method('getRate')
+            ->will($this->onConsecutiveCalls($storeTaxRate, $customerTaxRate));
+
+        return $taxCalculation;
+    }
+
+    /**
+     * Setup weee helper with an array of methodName, returnValue
+     *
+     * @param array $weeeConfig
+     * @return \PHPUnit_Framework_MockObject_MockObject|\Magento\Weee\Helper\Data
+     */
+    protected function setupWeeeHelper($weeeConfig)
+    {
+        $weeeHelper = $this->getMock('Magento\Weee\Helper\Data', [], [], '', false);
+
+        foreach ($weeeConfig as $method => $value) {
+            $weeeHelper->expects($this->any())->method($method)->will($this->returnValue($value));
+        }
+
+        return $weeeHelper;
+    }
+
+    /**
+     * Setup an item mock
+     *
+     * @param float $itemQty
+     * @return \PHPUnit_Framework_MockObject_MockObject|\Magento\Sales\Model\Quote\Item
+     */
+    protected function setupItemMock($itemQty)
+    {
+        $itemMock = $this->getMock(
+            'Magento\Sales\Model\Quote\Item',
+            [
+                'getProduct',
+                'getQuote',
+                'getAddress',
+                'getTotalQty',
+                '__wakeup',
+            ],
+            [],
+            '',
+            false
+        );
+
+        $productMock = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false);
+        $itemMock->expects($this->any())->method('getProduct')->will($this->returnValue($productMock));
+        $itemMock->expects($this->any())->method('getTotalQty')->will($this->returnValue($itemQty));
+
+        return $itemMock;
+    }
+
+    /**
+     * Setup address mock
+     *
+     * @param \PHPUnit_Framework_MockObject_MockObject|\Magento\Sales\Model\Quote\Item $itemMock
+     * @param boolean $isWeeeTaxable
+     * @param array   $itemData
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function setupAddressMock($itemMock, $isWeeeTaxable, $itemData)
+    {
+        $addressMock = $this->getMock(
+            'Magento\Sales\Model\Quote\Address',
+            [
+                '__wakeup',
+                'getAllNonNominalItems',
+                'getQuote',
+                'getWeeeCodeToItemMap',
+                'getExtraTaxableDetails',
+            ],
+            [],
+            '',
+            false
+        );
+
+        $map = [];
+        $extraDetails = [];
+        if ($isWeeeTaxable) {
+            $code = 'weee1-myWeeeCode';
+            $map = [$code => $itemMock];
+            $extraDetails = [
+                'weee' => [
+                    'sequence-1' => [
+                        [
+                            CTC::KEY_TAX_DETAILS_TYPE => 'weee',
+                            CTC::KEY_TAX_DETAILS_CODE => $code,
+                            CTC::KEY_TAX_DETAILS_PRICE_EXCL_TAX => $itemData['weee_tax_applied_amount'],
+                            CTC::KEY_TAX_DETAILS_BASE_PRICE_EXCL_TAX => $itemData['base_weee_tax_applied_amount'],
+                            CTC::KEY_TAX_DETAILS_PRICE_INCL_TAX => $itemData['weee_tax_applied_amount_incl_tax'],
+                            CTC::KEY_TAX_DETAILS_BASE_PRICE_INCL_TAX =>
+                                $itemData['base_weee_tax_applied_amount_incl_tax'],
+                            CTC::KEY_TAX_DETAILS_ROW_TOTAL => $itemData['weee_tax_applied_row_amount'],
+                            CTC::KEY_TAX_DETAILS_BASE_ROW_TOTAL => $itemData['base_weee_tax_applied_row_amnt'],
+                            CTC::KEY_TAX_DETAILS_ROW_TOTAL_INCL_TAX =>
+                                $itemData['weee_tax_applied_row_amount_incl_tax'],
+                            CTC::KEY_TAX_DETAILS_BASE_ROW_TOTAL_INCL_TAX =>
+                                $itemData['base_weee_tax_applied_row_amnt_incl_tax'],
+                        ]
+                    ]
+                ]
+            ];
+        }
+
+        $quoteMock = $this->getMock('Magento\Sales\Model\Quote', [], [], '', false);
+        $storeMock = $this->getMock('Magento\Store\Model\Store', ['__wakeup', 'convertPrice'], [], '', false);
+        $storeMock->expects($this->any())->method('convertPrice')->will($this->returnArgument(0));
+        $quoteMock->expects($this->any())->method('getStore')->will($this->returnValue($storeMock));
+
+        $addressMock->expects($this->any())->method('getAllNonNominalItems')->will($this->returnValue([$itemMock]));
+        $addressMock->expects($this->any())->method('getQuote')->will($this->returnValue($quoteMock));
+        $addressMock->expects($this->any())->method('getWeeeCodeToItemMap')->will($this->returnValue($map));
+        $addressMock->expects($this->any())->method('getExtraTaxableDetails')->will($this->returnValue($extraDetails));
+
+        return $addressMock;
+    }
+
+    /**
+     * Verify that correct fields of item has been set
+     *
+     * @param \PHPUnit_Framework_MockObject_MockObject|\Magento\Sales\Model\Quote\Item $item
+     * @param array $itemData
+     */
+    public function verifyItem(\Magento\Sales\Model\Quote\Item $item, $itemData)
+    {
+        foreach ($itemData as $key => $value) {
+            $this->assertEquals($value, $item->getData($key), 'item ' . $key . ' is incorrect');
+        }
+    }
+
+    /**
+     * Verify that correct fields of address has been set
+     *
+     * @param \PHPUnit_Framework_MockObject_MockObject|\Magento\Sales\Model\Quote\Address $address
+     * @param array $addressData
+     */
+    public function verifyAddress(\Magento\Sales\Model\Quote\Address $address, $addressData)
+    {
+        foreach ($addressData as $key => $value) {
+            $this->assertEquals($value, $address->getData($key), 'address ' . $key . ' is incorrect');
+        }
+    }
+
+    /**
+     * Test the collect function of the weee collector
+     *
+     * @param array $taxConfig
+     * @param array $weeeConfig
+     * @param array $taxRates
+     * @param array $itemData
+     * @param float $itemQty
+     * @param array $addressData
+     * @dataProvider collectDataProvider
+     */
+    public function testCollect($taxConfig, $weeeConfig, $taxRates, $itemData, $itemQty, $addressData = [])
+    {
+        $itemMock = $this->setupItemMock($itemQty);
+        $addressMock = $this->setupAddressMock($itemMock, $weeeConfig['isTaxable'], $itemData);
+
+        $taxHelper = $this->setupTaxHelper($taxConfig);
+        $weeeHelper = $this->setupWeeeHelper($weeeConfig);
+        $calculator = $this->setupTaxCalculation($taxRates);
+
+        $arguments = [
+            'taxData' => $taxHelper,
+            'calculation' => $calculator,
+            'weeeData' => $weeeHelper,
+        ];
+
+        $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->weeeCollector = $helper->getObject('Magento\Weee\Model\Total\Quote\WeeeTax', $arguments);
+
+        $this->weeeCollector->collect($addressMock);
+
+        $this->verifyItem($itemMock, $itemData);
+        $this->verifyAddress($addressMock, $addressData);
+    }
+
+    /**
+     * Data provider for testCollect
+     *
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     * Multiple datasets
+     *
+     * @return array
+     */
+    public function collectDataProvider()
+    {
+        // 1. When the Weee is not taxable, this collector does not change the item or the address data
+        // 2. If the Weee amount is included in the subtotal, then it is not included in the 'weee_amount' field
+
+        $data = [];
+
+        $data['price_incl_tax_weee_taxable_unit_included_in_subtotal'] = [
+            'tax_config' => [
+                'priceIncludesTax' => true,
+                'getCalculationAgorithm' => Calculation::CALC_UNIT_BASE,
+            ],
+            'weee_config' => [
+                'isEnabled' => true,
+                'includeInSubtotal' => true,
+                'isTaxable' => true,
+                'getApplied' => [],
+                'getProductWeeeAttributes' => [
+                    new \Magento\Framework\Object(
+                        [
+                            'name' => 'Recycling Fee',
+                            'amount' => 10,
+                        ]
+                    ),
+                ],
+            ],
+            'tax_rates' => [
+                'store_tax_rate' => 8.25,
+                'customer_tax_rate' => 8.25,
+            ],
+            'item' => [
+                'weee_tax_applied_amount' => 9.24,
+                'base_weee_tax_applied_amount' => 9.24,
+                'weee_tax_applied_row_amount' => 18.48,
+                'base_weee_tax_applied_row_amnt' => 18.48,
+                'weee_tax_applied_amount_incl_tax' => 10,
+                'base_weee_tax_applied_amount_incl_tax' => 10,
+                'weee_tax_applied_row_amount_incl_tax' => 20,
+                'base_weee_tax_applied_row_amnt_incl_tax' => 20,
+            ],
+            'item_qty' => 2,
+            'address_data' => [
+                'subtotal' => 18.48,
+                'base_subtotal' => 18.48,
+                'subtotal_incl_tax' => 20,
+                'base_subtotal_incl_tax' => 20,
+                'weee_amount' => 0,
+                'base_weee_amount' => 0,
+            ]
+        ];
+
+        $data['price_incl_tax_weee_taxable_unit_not_included_in_subtotal'] = [
+            'tax_config' => [
+                'priceIncludesTax' => true,
+                'getCalculationAgorithm' => Calculation::CALC_UNIT_BASE,
+            ],
+            'weee_config' => [
+                'isEnabled' => true,
+                'includeInSubtotal' => false,
+                'isTaxable' => true,
+                'getApplied' => [],
+                'getProductWeeeAttributes' => [
+                    new \Magento\Framework\Object(
+                        [
+                            'name' => 'Recycling Fee',
+                            'amount' => 10,
+                        ]
+                    ),
+                ],
+            ],
+            'tax_rates' => [
+                'store_tax_rate' => 8.25,
+                'customer_tax_rate' => 8.25,
+            ],
+            'item' => [
+                'weee_tax_applied_amount' => 9.24,
+                'base_weee_tax_applied_amount' => 9.24,
+                'weee_tax_applied_row_amount' => 18.48,
+                'base_weee_tax_applied_row_amnt' => 18.48,
+                'weee_tax_applied_amount_incl_tax' => 10,
+                'base_weee_tax_applied_amount_incl_tax' => 10,
+                'weee_tax_applied_row_amount_incl_tax' => 20,
+                'base_weee_tax_applied_row_amnt_incl_tax' => 20,
+            ],
+            'item_qty' => 2,
+            'address_data' => [
+                'subtotal' => 0,
+                'base_subtotal' => 0,
+                'subtotal_incl_tax' => 20,
+                'base_subtotal_incl_tax' => 20,
+                'weee_amount' => 18.48,
+                'base_weee_amount' => 18.48,
+            ]
+        ];
+
+        $data['price_excl_tax_weee_taxable_unit_included_in_subtotal'] = [
+            'tax_config' => [
+                'priceIncludesTax' => false,
+                'getCalculationAgorithm' => Calculation::CALC_UNIT_BASE,
+            ],
+            'weee_config' => [
+                'isEnabled' => true,
+                'includeInSubtotal' => true,
+                'isTaxable' => true,
+                'getApplied' => [],
+                'getProductWeeeAttributes' => [
+                    new \Magento\Framework\Object(
+                        [
+                            'name' => 'Recycling Fee',
+                            'amount' => 10,
+                        ]
+                    ),
+                ],
+            ],
+            'tax_rates' => [
+                'store_tax_rate' => 8.25,
+                'customer_tax_rate' => 8.25,
+            ],
+            'item' => [
+                'weee_tax_applied_amount' => 10,
+                'base_weee_tax_applied_amount' => 10,
+                'weee_tax_applied_row_amount' => 20,
+                'base_weee_tax_applied_row_amnt' => 20,
+                'weee_tax_applied_amount_incl_tax' => 10.83,
+                'base_weee_tax_applied_amount_incl_tax' => 10.83,
+                'weee_tax_applied_row_amount_incl_tax' => 21.66,
+                'base_weee_tax_applied_row_amnt_incl_tax' => 21.66,
+            ],
+            'item_qty' => 2,
+            'address_data' => [
+                'subtotal' => 20,
+                'base_subtotal' => 20,
+                'subtotal_incl_tax' => 21.66,
+                'base_subtotal_incl_tax' => 21.66,
+                'weee_amount' => 0,
+                'base_weee_amount' => 0,
+            ]
+        ];
+
+        $data['price_incl_tax_weee_non_taxable_unit_included_in_subtotal'] = [
+            'tax_config' => [
+                'priceIncludesTax' => true,
+                'getCalculationAgorithm' => Calculation::CALC_UNIT_BASE,
+            ],
+            'weee_config' => [
+                'isEnabled' => true,
+                'includeInSubtotal' => true,
+                'isTaxable' => false,
+                'getApplied' => [],
+                'getProductWeeeAttributes' => [
+                    new \Magento\Framework\Object(
+                        [
+                            'name' => 'Recycling Fee',
+                            'amount' => 10,
+                        ]
+                    ),
+                ],
+            ],
+            'tax_rates' => [
+                'store_tax_rate' => 8.25,
+                'customer_tax_rate' => 8.25,
+            ],
+            'item' => [
+            ],
+            'item_qty' => 2,
+        ];
+
+        $data['price_excl_tax_weee_non_taxable_unit_include_in_subtotal'] = [
+            'tax_config' => [
+                'priceIncludesTax' => false,
+                'getCalculationAgorithm' => Calculation::CALC_UNIT_BASE,
+            ],
+            'weee_config' => [
+                'isEnabled' => true,
+                'includeInSubtotal' => true,
+                'isTaxable' => false,
+                'getApplied' => [],
+                'getProductWeeeAttributes' => [
+                    new \Magento\Framework\Object(
+                        [
+                            'name' => 'Recycling Fee',
+                            'amount' => 10,
+                        ]
+                    ),
+                ],
+            ],
+            'tax_rates' => [
+                'store_tax_rate' => 8.25,
+                'customer_tax_rate' => 8.25,
+            ],
+            'item' => [
+            ],
+            'item_qty' => 2,
+        ];
+        $data['price_incl_tax_weee_taxable_row_include_in_subtotal'] = [
+            'tax_config' => [
+                'priceIncludesTax' => true,
+                'getCalculationAgorithm' => Calculation::CALC_ROW_BASE,
+            ],
+            'weee_config' => [
+                'isEnabled' => true,
+                'includeInSubtotal' => true,
+                'isTaxable' => true,
+                'getApplied' => [],
+                'getProductWeeeAttributes' => [
+                    new \Magento\Framework\Object(
+                        [
+                            'name' => 'Recycling Fee',
+                            'amount' => 10,
+                        ]
+                    ),
+                ],
+            ],
+            'tax_rates' => [
+                'store_tax_rate' => 8.25,
+                'customer_tax_rate' => 8.25,
+            ],
+            'item' => [
+                'weee_tax_applied_amount' => 9.24,
+                'base_weee_tax_applied_amount' => 9.24,
+                'weee_tax_applied_row_amount' => 18.48,
+                'base_weee_tax_applied_row_amnt' => 18.48,
+                'weee_tax_applied_amount_incl_tax' => 10,
+                'base_weee_tax_applied_amount_incl_tax' => 10,
+                'weee_tax_applied_row_amount_incl_tax' => 20,
+                'base_weee_tax_applied_row_amnt_incl_tax' => 20,
+            ],
+            'item_qty' => 2,
+            'address_data' => [
+                'subtotal' => 18.48,
+                'base_subtotal' => 18.48,
+                'subtotal_incl_tax' => 20,
+                'base_subtotal_incl_tax' => 20,
+                'weee_amount' => 0,
+                'base_weee_amount' => 0,
+            ]
+        ];
+
+        $data['price_excl_tax_weee_taxable_row_include_in_subtotal'] = [
+            'tax_config' => [
+                'priceIncludesTax' => false,
+                'getCalculationAgorithm' => Calculation::CALC_ROW_BASE,
+            ],
+            'weee_config' => [
+                'isEnabled' => true,
+                'includeInSubtotal' => true,
+                'isTaxable' => true,
+                'getApplied' => [],
+                'getProductWeeeAttributes' => [
+                    new \Magento\Framework\Object(
+                        [
+                            'name' => 'Recycling Fee',
+                            'amount' => 10,
+                        ]
+                    ),
+                ],
+            ],
+            'tax_rates' => [
+                'store_tax_rate' => 8.25,
+                'customer_tax_rate' => 8.25,
+            ],
+            'item' => [
+                'weee_tax_applied_amount' => 10,
+                'base_weee_tax_applied_amount' => 10,
+                'weee_tax_applied_row_amount' => 20,
+                'base_weee_tax_applied_row_amnt' => 20,
+                'weee_tax_applied_amount_incl_tax' => 10.83,
+                'base_weee_tax_applied_amount_incl_tax' => 10.83,
+                'weee_tax_applied_row_amount_incl_tax' => 21.65,
+                'base_weee_tax_applied_row_amnt_incl_tax' => 21.65,
+            ],
+            'item_qty' => 2,
+            'address_data' => [
+                'subtotal' => 20,
+                'base_subtotal' => 20,
+                'subtotal_incl_tax' => 21.65,
+                'base_subtotal_incl_tax' => 21.65,
+                'weee_amount' => 0,
+                'base_weee_amount' => 0,
+            ]
+        ];
+
+        $data['price_incl_tax_weee_non_taxable_row_include_in_subtotal'] = [
+            'tax_config' => [
+                'priceIncludesTax' => true,
+                'getCalculationAgorithm' => Calculation::CALC_ROW_BASE,
+            ],
+            'weee_config' => [
+                'isEnabled' => true,
+                'includeInSubtotal' => true,
+                'isTaxable' => false,
+                'getApplied' => [],
+                'getProductWeeeAttributes' => [
+                    new \Magento\Framework\Object(
+                        [
+                            'name' => 'Recycling Fee',
+                            'amount' => 10,
+                        ]
+                    ),
+                ],
+            ],
+            'tax_rates' => [
+                'store_tax_rate' => 8.25,
+                'customer_tax_rate' => 8.25,
+            ],
+            'item' => [
+            ],
+            'item_qty' => 2,
+        ];
+
+        $data['price_excl_tax_weee_non_taxable_row_not_included_in_subtotal'] = [
+            'tax_config' => [
+                'priceIncludesTax' => false,
+                'getCalculationAgorithm' => Calculation::CALC_ROW_BASE,
+            ],
+            'weee_config' => [
+                'isEnabled' => true,
+                'includeInSubtotal' => false,
+                'isTaxable' => false,
+                'getApplied' => [],
+                'getProductWeeeAttributes' => [
+                    new \Magento\Framework\Object(
+                        [
+                            'name' => 'Recycling Fee',
+                            'amount' => 10,
+                        ]
+                    ),
+                ],
+            ],
+            'tax_rates' => [
+                'store_tax_rate' => 8.25,
+                'customer_tax_rate' => 8.25,
+            ],
+            'item' => [
+            ],
+            'item_qty' => 2,
+        ];
+
+        return $data;
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Weee/Model/Total/Quote/WeeeTest.php b/dev/tests/unit/testsuite/Magento/Weee/Model/Total/Quote/WeeeTest.php
index 54ea80cd854745bae0c529aad993ce3be93cc37f..07684fb048fb3772701539257e4fa9cab7d48b1e 100644
--- a/dev/tests/unit/testsuite/Magento/Weee/Model/Total/Quote/WeeeTest.php
+++ b/dev/tests/unit/testsuite/Magento/Weee/Model/Total/Quote/WeeeTest.php
@@ -168,7 +168,7 @@ class WeeeTest extends \PHPUnit_Framework_TestCase
      * Verify that correct fields of address has been set
      *
      * @param \PHPUnit_Framework_MockObject_MockObject|\Magento\Sales\Model\Quote\Address $address
-     * @param $itemData
+     * @param $addressData
      */
     public function verifyAddress(\Magento\Sales\Model\Quote\Address $address, $addressData)
     {
@@ -223,7 +223,13 @@ class WeeeTest extends \PHPUnit_Framework_TestCase
     public function collectDataProvider()
     {
         $data = [];
-        $data['price_incl_tax_weee_taxable_unit'] = [
+
+        // 1. This collector does not compute tax.  Instead it sets up various fields for the tax calculation
+        // 2. When the Weee is not taxable, this collector will change the address data as follows:
+        // 2a. If Weee is included in the subtotal, the 'subtotal' fields are populated
+        // 2b. Otherwise the 'weee_amount' fields are populated
+
+        $data['price_incl_tax_weee_taxable_unit_included_in_subtotal'] = [
             'tax_config' => [
                 'priceIncludesTax' => true,
                 'getCalculationAgorithm' => Calculation::CALC_UNIT_BASE,
@@ -247,27 +253,19 @@ class WeeeTest extends \PHPUnit_Framework_TestCase
                 'customer_tax_rate' => 8.25,
             ],
             'item' => [
-                'weee_tax_applied_amount' => 9.24,
-                'base_weee_tax_applied_amount' => 9.24,
-                'weee_tax_applied_row_amount' => 18.48,
-                'base_weee_tax_applied_row_amnt' => 18.48,
+                'weee_tax_applied_amount' => 10,
+                'base_weee_tax_applied_amount' => 10,
+                'weee_tax_applied_row_amount' => 20,
+                'base_weee_tax_applied_row_amnt' => 20,
                 'weee_tax_applied_amount_incl_tax' => 10,
                 'base_weee_tax_applied_amount_incl_tax' => 10,
                 'weee_tax_applied_row_amount_incl_tax' => 20,
                 'base_weee_tax_applied_row_amnt_incl_tax' => 20,
-                'extra_taxable_amount' => 10,
-                'base_extra_taxable_amount' => 10,
-                'extra_row_taxable_amount' => 20,
-                'base_extra_row_taxable_amount' => 20,
             ],
             'item_qty' => 2,
             'address_data' => [
                 'subtotal_incl_tax' => 20,
                 'base_subtotal_incl_tax' => 20,
-                'weee' => 18.48,
-                'base_weee' => 18.48,
-                'extra_tax_amount' => 0,
-                'base_extra_tax_amount' => 0,
             ]
         ];
 
@@ -295,31 +293,23 @@ class WeeeTest extends \PHPUnit_Framework_TestCase
                 'customer_tax_rate' => 8.25,
             ],
             'item' => [
-                'weee_tax_applied_amount' => 9.24,
-                'base_weee_tax_applied_amount' => 9.24,
-                'weee_tax_applied_row_amount' => 18.48,
-                'base_weee_tax_applied_row_amnt' => 18.48,
+                'weee_tax_applied_amount' => 10,
+                'base_weee_tax_applied_amount' => 10,
+                'weee_tax_applied_row_amount' => 20,
+                'base_weee_tax_applied_row_amnt' => 20,
                 'weee_tax_applied_amount_incl_tax' => 10,
                 'base_weee_tax_applied_amount_incl_tax' => 10,
                 'weee_tax_applied_row_amount_incl_tax' => 20,
                 'base_weee_tax_applied_row_amnt_incl_tax' => 20,
-                'extra_taxable_amount' => 10,
-                'base_extra_taxable_amount' => 10,
-                'extra_row_taxable_amount' => 20,
-                'base_extra_row_taxable_amount' => 20,
             ],
             'item_qty' => 2,
             'address_data' => [
                 'subtotal_incl_tax' => 20,
                 'base_subtotal_incl_tax' => 20,
-                'subtotal' => 0,
-                'base_subtotal' => 0,
-                'weee_amount' => 18.48,
-                'base_weee_amount' => 18.48,
             ]
         ];
 
-        $data['price_excl_tax_weee_taxable_unit'] = [
+        $data['price_excl_tax_weee_taxable_unit_included_in_subtotal'] = [
             'tax_config' => [
                 'priceIncludesTax' => false,
                 'getCalculationAgorithm' => Calculation::CALC_UNIT_BASE,
@@ -347,19 +337,19 @@ class WeeeTest extends \PHPUnit_Framework_TestCase
                 'base_weee_tax_applied_amount' => 10,
                 'weee_tax_applied_row_amount' => 20,
                 'base_weee_tax_applied_row_amnt' => 20,
-                'weee_tax_applied_amount_incl_tax' => 10.83,
-                'base_weee_tax_applied_amount_incl_tax' => 10.83,
-                'weee_tax_applied_row_amount_incl_tax' => 21.66,
-                'base_weee_tax_applied_row_amnt_incl_tax' => 21.66,
-                'extra_taxable_amount' => 10,
-                'base_extra_taxable_amount' => 10,
-                'extra_row_taxable_amount' => 20,
-                'base_extra_row_taxable_amount' => 20,
+                'weee_tax_applied_amount_incl_tax' => 10,
+                'base_weee_tax_applied_amount_incl_tax' => 10,
+                'weee_tax_applied_row_amount_incl_tax' => 20,
+                'base_weee_tax_applied_row_amnt_incl_tax' => 20,
             ],
             'item_qty' => 2,
+            'address_data' => [
+                'subtotal_incl_tax' => 20,
+                'base_subtotal_incl_tax' => 20,
+            ]
         ];
 
-        $data['price_incl_tax_weee_taxable_unit'] = [
+        $data['price_incl_tax_weee_non_taxable_unit_included_in_subtotal'] = [
             'tax_config' => [
                 'priceIncludesTax' => true,
                 'getCalculationAgorithm' => Calculation::CALC_UNIT_BASE,
@@ -367,7 +357,7 @@ class WeeeTest extends \PHPUnit_Framework_TestCase
             'weee_config' => [
                 'isEnabled' => true,
                 'includeInSubtotal' => true,
-                'isTaxable' => true,
+                'isTaxable' => false,
                 'getApplied' => [],
                 'getProductWeeeAttributes' => [
                     new \Magento\Framework\Object(
@@ -383,33 +373,29 @@ class WeeeTest extends \PHPUnit_Framework_TestCase
                 'customer_tax_rate' => 8.25,
             ],
             'item' => [
-                'weee_tax_applied_amount' => 9.24,
-                'base_weee_tax_applied_amount' => 9.24,
-                'weee_tax_applied_row_amount' => 18.48,
-                'base_weee_tax_applied_row_amnt' => 18.48,
+                'weee_tax_applied_amount' => 10,
+                'base_weee_tax_applied_amount' => 10,
+                'weee_tax_applied_row_amount' => 20,
+                'base_weee_tax_applied_row_amnt' => 20,
                 'weee_tax_applied_amount_incl_tax' => 10,
                 'base_weee_tax_applied_amount_incl_tax' => 10,
                 'weee_tax_applied_row_amount_incl_tax' => 20,
                 'base_weee_tax_applied_row_amnt_incl_tax' => 20,
-                'extra_taxable_amount' => 10,
-                'base_extra_taxable_amount' => 10,
-                'extra_row_taxable_amount' => 20,
-                'base_extra_row_taxable_amount' => 20,
             ],
             'item_qty' => 2,
             'address_data' => [
                 'subtotal_incl_tax' => 20,
                 'base_subtotal_incl_tax' => 20,
-                'extra_subtotal_amount' => 18.48,
-                'base_extra_subtotal_amount' => 18.48,
-                'extra_tax_amount' => 1.52,
-                'base_extra_tax_amount' => 1.52,
+                'subtotal' => 20,
+                'base_subtotal' => 20,
+                'weee_amount' => 0,
+                'base_weee_amount' => 0,
             ]
         ];
 
-        $data['price_incl_tax_weee_non_taxable_unit'] = [
+        $data['price_excl_tax_weee_non_taxable_unit_included_in_subtotal'] = [
             'tax_config' => [
-                'priceIncludesTax' => true,
+                'priceIncludesTax' => false,
                 'getCalculationAgorithm' => Calculation::CALC_UNIT_BASE,
             ],
             'weee_config' => [
@@ -439,23 +425,27 @@ class WeeeTest extends \PHPUnit_Framework_TestCase
                 'base_weee_tax_applied_amount_incl_tax' => 10,
                 'weee_tax_applied_row_amount_incl_tax' => 20,
                 'base_weee_tax_applied_row_amnt_incl_tax' => 20,
-                'extra_taxable_amount' => 0,
-                'base_extra_taxable_amount' => 0,
-                'extra_row_taxable_amount' => 0,
-                'base_extra_row_taxable_amount' => 0,
             ],
             'item_qty' => 2,
+            'address_data' => [
+                'subtotal_incl_tax' => 20,
+                'base_subtotal_incl_tax' => 20,
+                'subtotal' => 20,
+                'base_subtotal' => 20,
+                'weee_amount' => 0,
+                'base_weee_amount' => 0,
+            ]
         ];
 
-        $data['price_excl_tax_weee_non_taxable_unit'] = [
+        $data['price_incl_tax_weee_taxable_row_included_in_subtotal'] = [
             'tax_config' => [
-                'priceIncludesTax' => false,
-                'getCalculationAgorithm' => Calculation::CALC_UNIT_BASE,
+                'priceIncludesTax' => true,
+                'getCalculationAgorithm' => Calculation::CALC_ROW_BASE,
             ],
             'weee_config' => [
                 'isEnabled' => true,
                 'includeInSubtotal' => true,
-                'isTaxable' => false,
+                'isTaxable' => true,
                 'getApplied' => [],
                 'getProductWeeeAttributes' => [
                     new \Magento\Framework\Object(
@@ -479,16 +469,17 @@ class WeeeTest extends \PHPUnit_Framework_TestCase
                 'base_weee_tax_applied_amount_incl_tax' => 10,
                 'weee_tax_applied_row_amount_incl_tax' => 20,
                 'base_weee_tax_applied_row_amnt_incl_tax' => 20,
-                'extra_taxable_amount' => 0,
-                'base_extra_taxable_amount' => 0,
-                'extra_row_taxable_amount' => 0,
-                'base_extra_row_taxable_amount' => 0,
             ],
             'item_qty' => 2,
+            'address_data' => [
+                'subtotal_incl_tax' => 20,
+                'base_subtotal_incl_tax' => 20,
+            ]
         ];
-        $data['price_incl_tax_weee_taxable_row'] = [
+
+        $data['price_excl_tax_weee_taxable_row_included_in_subtotal'] = [
             'tax_config' => [
-                'priceIncludesTax' => true,
+                'priceIncludesTax' => false,
                 'getCalculationAgorithm' => Calculation::CALC_ROW_BASE,
             ],
             'weee_config' => [
@@ -510,31 +501,31 @@ class WeeeTest extends \PHPUnit_Framework_TestCase
                 'customer_tax_rate' => 8.25,
             ],
             'item' => [
-                'weee_tax_applied_amount' => 9.24,
-                'base_weee_tax_applied_amount' => 9.24,
-                'weee_tax_applied_row_amount' => 18.48,
-                'base_weee_tax_applied_row_amnt' => 18.48,
+                'weee_tax_applied_amount' => 10,
+                'base_weee_tax_applied_amount' => 10,
+                'weee_tax_applied_row_amount' => 20,
+                'base_weee_tax_applied_row_amnt' => 20,
                 'weee_tax_applied_amount_incl_tax' => 10,
                 'base_weee_tax_applied_amount_incl_tax' => 10,
                 'weee_tax_applied_row_amount_incl_tax' => 20,
                 'base_weee_tax_applied_row_amnt_incl_tax' => 20,
-                'extra_taxable_amount' => 10,
-                'base_extra_taxable_amount' => 10,
-                'extra_row_taxable_amount' => 20,
-                'base_extra_row_taxable_amount' => 20,
             ],
             'item_qty' => 2,
+            'address_data' => [
+                'subtotal_incl_tax' => 20,
+                'base_subtotal_incl_tax' => 20,
+            ]
         ];
 
-        $data['price_excl_tax_weee_taxable_row'] = [
+        $data['price_incl_tax_weee_non_taxable_row_included_in_subtotal'] = [
             'tax_config' => [
-                'priceIncludesTax' => false,
+                'priceIncludesTax' => true,
                 'getCalculationAgorithm' => Calculation::CALC_ROW_BASE,
             ],
             'weee_config' => [
                 'isEnabled' => true,
                 'includeInSubtotal' => true,
-                'isTaxable' => true,
+                'isTaxable' => false,
                 'getApplied' => [],
                 'getProductWeeeAttributes' => [
                     new \Magento\Framework\Object(
@@ -554,21 +545,25 @@ class WeeeTest extends \PHPUnit_Framework_TestCase
                 'base_weee_tax_applied_amount' => 10,
                 'weee_tax_applied_row_amount' => 20,
                 'base_weee_tax_applied_row_amnt' => 20,
-                'weee_tax_applied_amount_incl_tax' => 10.83,
-                'base_weee_tax_applied_amount_incl_tax' => 10.83,
-                'weee_tax_applied_row_amount_incl_tax' => 21.65,
-                'base_weee_tax_applied_row_amnt_incl_tax' => 21.65,
-                'extra_taxable_amount' => 10,
-                'base_extra_taxable_amount' => 10,
-                'extra_row_taxable_amount' => 20,
-                'base_extra_row_taxable_amount' => 20,
+                'weee_tax_applied_amount_incl_tax' => 10,
+                'base_weee_tax_applied_amount_incl_tax' => 10,
+                'weee_tax_applied_row_amount_incl_tax' => 20,
+                'base_weee_tax_applied_row_amnt_incl_tax' => 20,
             ],
             'item_qty' => 2,
+            'address_data' => [
+                'subtotal_incl_tax' => 20,
+                'base_subtotal_incl_tax' => 20,
+                'subtotal' => 20,
+                'base_subtotal' => 20,
+                'weee_amount' => 0,
+                'base_weee_amount' => 0,
+            ]
         ];
 
-        $data['price_incl_tax_weee_non_taxable_row'] = [
+        $data['price_excl_tax_weee_non_taxable_row_included_in_subtotal'] = [
             'tax_config' => [
-                'priceIncludesTax' => true,
+                'priceIncludesTax' => false,
                 'getCalculationAgorithm' => Calculation::CALC_ROW_BASE,
             ],
             'weee_config' => [
@@ -598,22 +593,26 @@ class WeeeTest extends \PHPUnit_Framework_TestCase
                 'base_weee_tax_applied_amount_incl_tax' => 10,
                 'weee_tax_applied_row_amount_incl_tax' => 20,
                 'base_weee_tax_applied_row_amnt_incl_tax' => 20,
-                'extra_taxable_amount' => 0,
-                'base_extra_taxable_amount' => 0,
-                'extra_row_taxable_amount' => 0,
-                'base_extra_row_taxable_amount' => 0,
             ],
             'item_qty' => 2,
+            'address_data' => [
+                'subtotal_incl_tax' => 20,
+                'base_subtotal_incl_tax' => 20,
+                'subtotal' => 20,
+                'base_subtotal' => 20,
+                'weee_amount' => 0,
+                'base_weee_amount' => 0,
+            ]
         ];
 
-        $data['price_excl_tax_weee_non_taxable_row'] = [
+        $data['price_excl_tax_weee_non_taxable_row_not_included_in_subtotal'] = [
             'tax_config' => [
                 'priceIncludesTax' => false,
                 'getCalculationAgorithm' => Calculation::CALC_ROW_BASE,
             ],
             'weee_config' => [
                 'isEnabled' => true,
-                'includeInSubtotal' => true,
+                'includeInSubtotal' => false,
                 'isTaxable' => false,
                 'getApplied' => [],
                 'getProductWeeeAttributes' => [
@@ -638,13 +637,18 @@ class WeeeTest extends \PHPUnit_Framework_TestCase
                 'base_weee_tax_applied_amount_incl_tax' => 10,
                 'weee_tax_applied_row_amount_incl_tax' => 20,
                 'base_weee_tax_applied_row_amnt_incl_tax' => 20,
-                'extra_taxable_amount' => 0,
-                'base_extra_taxable_amount' => 0,
-                'extra_row_taxable_amount' => 0,
-                'base_extra_row_taxable_amount' => 0,
             ],
             'item_qty' => 2,
+            'address_data' => [
+                'subtotal_incl_tax' => 20,
+                'base_subtotal_incl_tax' => 20,
+                'subtotal' => 0,
+                'base_subtotal' => 0,
+                'weee_amount' => 20,
+                'base_weee_amount' => 20,
+            ]
         ];
+
         return $data;
     }
-}
\ No newline at end of file
+}
diff --git a/lib/internal/Magento/Framework/App/Language/Config.php b/lib/internal/Magento/Framework/App/Language/Config.php
new file mode 100644
index 0000000000000000000000000000000000000000..1b569b62e47b6517f7ecf6104fd7ea8ac80fa09f
--- /dev/null
+++ b/lib/internal/Magento/Framework/App/Language/Config.php
@@ -0,0 +1,152 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\App\Language;
+
+use Magento\Framework\Config\Dom;
+
+/**
+ * Language pack configuration file
+ */
+class Config
+{
+    /**
+     * Data extracted from the configuration file
+     *
+     * @var array
+     */
+    protected $_data;
+
+    /**
+     * Constructor
+     *
+     * @param string $source
+     * @throws \Magento\Framework\Exception
+     */
+    public function __construct($source)
+    {
+        $config = new \DOMDocument();
+        $config->loadXML($source);
+        $errors = Dom::validateDomDocument($config, $this->getSchemaFile());
+        if (!empty($errors)) {
+            throw new \Magento\Framework\Exception("Invalid Document: \n" . implode("\n", $errors));
+        }
+        $this->_data = $this->_extractData($config);
+    }
+
+    /**
+     * Get absolute path to validation scheme for language.xml
+     *
+     * @return string
+     */
+    protected function getSchemaFile()
+    {
+        return __DIR__ . '/package.xsd';
+    }
+
+    /**
+     * Extract configuration data from the DOM structure
+     *
+     * @param \DOMDocument $dom
+     * @return array
+     */
+    protected function _extractData(\DOMDocument $dom)
+    {
+        /** @var $languageNode \DOMElement */
+        $languageNode = $dom->getElementsByTagName('language')->item(0);
+        /** @var $codeNode \DOMElement */
+        $codeNode = $languageNode->getElementsByTagName('code')->item(0);
+        /** @var $vendorNode \DOMElement */
+        $vendorNode = $languageNode->getElementsByTagName('vendor')->item(0);
+        /** @var $packageNode \DOMElement */
+        $packageNode = $languageNode->getElementsByTagName('package')->item(0);
+        /** @var $sortOrderNode \DOMElement */
+        $sortOrderNode = $languageNode->getElementsByTagName('sort_order')->item(0);
+        $use = [];
+        /** @var $useNode \DOMElement */
+        foreach ($languageNode->getElementsByTagName('use') as $useNode) {
+            $use[] = [
+                'vendor'  => $useNode->getAttribute('vendor'),
+                'package' => $useNode->getAttribute('package')
+            ];
+        }
+        return [
+            'code'       => $codeNode->nodeValue,
+            'vendor'     => $vendorNode->nodeValue,
+            'package'    => $packageNode->nodeValue,
+            'sort_order' => $sortOrderNode ? $sortOrderNode->nodeValue : 0,
+            'use'        => $use
+        ];
+    }
+
+    /**
+     * Language code
+     *
+     * @return string
+     */
+    public function getCode()
+    {
+        return $this->_data['code'];
+    }
+
+    /**
+     * Language vendor
+     *
+     * @return string
+     */
+    public function getVendor()
+    {
+        return $this->_data['vendor'];
+    }
+
+    /**
+     * Language package
+     *
+     * @return string
+     */
+    public function getPackage()
+    {
+        return $this->_data['package'];
+    }
+
+    /**
+     * Sort order
+     *
+     * @return null|int
+     */
+    public function getSortOrder()
+    {
+        return $this->_data['sort_order'];
+    }
+
+    /**
+     * Declaration of Inheritances
+     *
+     * @return string[][]
+     */
+    public function getUses()
+    {
+        return $this->_data['use'];
+    }
+}
diff --git a/lib/internal/Magento/Framework/App/Language/ConfigFactory.php b/lib/internal/Magento/Framework/App/Language/ConfigFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..ae60f01cd770539b5e895a225c9a05a915ffb5db
--- /dev/null
+++ b/lib/internal/Magento/Framework/App/Language/ConfigFactory.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Application language config factory
+ *
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\App\Language;
+
+/**
+ * @codeCoverageIgnore
+ */
+class ConfigFactory
+{
+    /**
+     * @var \Magento\Framework\ObjectManager
+     */
+    protected $_objectManager;
+
+    /**
+     * @param \Magento\Framework\ObjectManager $objectManager
+     */
+    public function __construct(\Magento\Framework\ObjectManager $objectManager)
+    {
+        $this->_objectManager = $objectManager;
+    }
+
+    /**
+     * Create config
+     *
+     * @param array $arguments
+     * @return Config
+     */
+    public function create(array $arguments = array())
+    {
+        return $this->_objectManager->create('Magento\Framework\App\Language\Config', $arguments);
+    }
+}
diff --git a/lib/internal/Magento/Framework/App/Language/Dictionary.php b/lib/internal/Magento/Framework/App/Language/Dictionary.php
index 02357f2c0b5adb7d26086d84413b36da60fada8f..622a01adc6718e71e6f411f9784acc0ca46ae936 100644
--- a/lib/internal/Magento/Framework/App/Language/Dictionary.php
+++ b/lib/internal/Magento/Framework/App/Language/Dictionary.php
@@ -24,6 +24,8 @@
 
 namespace Magento\Framework\App\Language;
 
+use \Magento\Framework\App\Filesystem;
+
 /**
  * A service for reading language package dictionaries
  */
@@ -34,17 +36,26 @@ class Dictionary
      */
     private $dir;
 
+    /**
+     * @var ConfigFactory
+     */
+    private $configFactory;
+
     /**
      * @var array
      */
-    private $packs = array();
+    private $packList = array();
 
     /**
-     * @param \Magento\Framework\App\Filesystem $filesystem
+     * @param Filesystem $filesystem
+     * @param ConfigFactory $configFactory
      */
-    public function __construct(\Magento\Framework\App\Filesystem $filesystem)
-    {
-        $this->dir = $filesystem->getDirectoryRead(\Magento\Framework\App\Filesystem::LOCALE_DIR);
+    public function __construct(
+        Filesystem $filesystem,
+        ConfigFactory $configFactory
+    ) {
+        $this->dir = $filesystem->getDirectoryRead(Filesystem::LOCALE_DIR);
+        $this->configFactory = $configFactory;
     }
 
     /**
@@ -58,125 +69,31 @@ class Dictionary
      */
     public function getDictionary($languageCode)
     {
+        $languages = [];
         $declarations = $this->dir->search('*/*/language.xml');
         foreach ($declarations as $file) {
-            list($vendor, $code) = explode('/', $file);
-            if ($languageCode == $code) {
-                $this->readPackDeclaration($vendor, $code);
-            }
-        }
-        $packs = [];
-        $this->collectInheritedPacks($languageCode, $packs);
-        uasort($packs, [$this, 'sortInherited']);
-        $result = [];
-        foreach ($packs as $info) {
-            $dictionary = $this->readPackCsv($info['vendor'], $info['code']);
-            $result = array_merge($result, $dictionary);
-        }
-        return $result;
-    }
-
-    /**
-     * Read declaration of the specified language pack
-     *
-     * Will recursively load any parent packs
-     *
-     * @param string $vendor
-     * @param string $code
-     * @return void
-     */
-    private function readPackDeclaration($vendor, $code)
-    {
-        if (isset($this->packs[$code][$vendor])) {
-            return;
-        }
-        $file = "{$vendor}/{$code}/language.xml";
-        $dom = new \DOMDocument();
-        $xml = $this->dir->readFile($file);
-        $dom->loadXML($xml);
-        $root = $dom->documentElement;
-        $this->assertVendor($vendor, $root);
-        $this->assertCode($code, $root);
-        $this->packs[$code][$vendor] = [
-            'vendor' => $vendor,
-            'code' => $code,
-            'sort_order' => $this->getSortOrder($root),
-        ];
-        $use = $this->getUse($root);
-        if ($use) {
-            foreach ($use as $info) {
-                $this->packs[$code][$vendor]['use'][] = $info;
-                $this->readPackDeclaration($info['vendor'], $info['code']);
-            }
-        }
-    }
-
-    /**
-     * Assert that vendor code in the declaration matches the one discovered in file system
-     *
-     * @param string $expected
-     * @param \DOMElement $root
-     * @return void
-     * @throws \LogicException
-     */
-    public static function assertVendor($expected, \DOMElement $root)
-    {
-        foreach ($root->getElementsByTagName('vendor') as $node) {
-            if ($expected != $node->nodeValue) {
-                throw new \LogicException('Vendor name mismatch');
-            }
-            break;
-        }
-    }
-
-    /**
-     * Assert that language code in the declaration matches the one discovered in file system
-     *
-     * @param string $expected
-     * @param \DOMElement $root
-     * @return void
-     * @throws \LogicException
-     */
-    public static function assertCode($expected, \DOMElement $root)
-    {
-        foreach ($root->getElementsByTagName('code') as $node) {
-            if ($expected != $node->nodeValue) {
-                throw new \LogicException('Language code name mismatch');
+            $xmlSource = $this->dir->readFile($file);
+            $languageConfig = $this->configFactory->create(['source' => $xmlSource]);
+            $this->packList[$languageConfig->getVendor()][$languageConfig->getPackage()] = $languageConfig;
+            if ($languageConfig->getCode() === $languageCode) {
+                $languages[] = $languageConfig;
             }
-            break;
         }
-    }
 
-    /**
-     * Read sort order from the declaration
-     *
-     * By default will be 0
-     *
-     * @param \DOMElement $root
-     * @return int
-     */
-    private function getSortOrder(\DOMElement $root)
-    {
-        foreach ($root->getElementsByTagName('sort_order') as $node) {
-            return (int)$node->nodeValue;
+        // Collect the inherited packages with meta-information of sorting
+        $packs = [];
+        foreach ($languages as $languageConfig) {
+            $this->collectInheritedPacks($languageConfig, $packs);
         }
-        return 0;
-    }
+        uasort($packs, [$this, 'sortInherited']);
 
-    /**
-     * Read information about reusing other packs from the declaration
-     *
-     * @param \DOMElement $root
-     * @return array
-     */
-    private function getUse(\DOMElement $root)
-    {
+        // Merge all packages of translation to one dictionary
         $result = [];
-        foreach ($root->getElementsByTagName('use') as $parent) {
-            $result[] = [
-                'vendor' => $parent->getAttribute('vendor'),
-                'code' => $parent->getAttribute('code'),
-            ];
+        foreach ($packs as $packInfo) {
+            /** @var Config $languageConfig */
+            $languageConfig = $packInfo['language'];
+            $dictionary = $this->readPackCsv($languageConfig->getVendor(), $languageConfig->getPackage());
+            $result = array_merge($result, $dictionary);
         }
         return $result;
     }
@@ -186,21 +103,24 @@ class Dictionary
      *
      * Record level of recursion (level of inheritance) for further use in sorting
      *
-     * @param string $code
+     * @param Config $languageConfig
      * @param array $result
      * @param int $level
      * @return void
      */
-    private function collectInheritedPacks($code, array &$result, $level = 0)
+    private function collectInheritedPacks($languageConfig, &$result, $level = 0)
     {
-        if (isset($this->packs[$code])) {
-            foreach ($this->packs[$code] as $vendor => $info) {
-                $info['inheritance_level'] = $level;
-                $result["{$code}|{$vendor}"] = $info;
-                if (isset($info['use'])) {
-                    foreach ($info['use'] as $reuse) {
-                        $this->collectInheritedPacks($reuse['code'], $result, $level + 1);
-                    }
+        $packKey = implode('|', [$languageConfig->getVendor(), $languageConfig->getPackage()]);
+        if (!isset($result[$packKey])) {
+            $result[$packKey] = [
+                'inheritance_level' => $level,
+                'sort_order'        => $languageConfig->getSortOrder(),
+                'language'          => $languageConfig
+            ];
+            foreach ($languageConfig->getUses() as $reuse) {
+                if (isset($this->packList[$reuse['vendor']][$reuse['package']])) {
+                    $parentLanguageConfig = $this->packList[$reuse['vendor']][$reuse['package']];
+                    $this->collectInheritedPacks($parentLanguageConfig, $result, $level + 1);
                 }
             }
         }
@@ -211,23 +131,21 @@ class Dictionary
      *
      * First sort by inheritance level descending, then by sort order ascending
      *
-     * @param array $a
-     * @param array $b
+     * @param array $current
+     * @param array $next
      * @return int
      * @SuppressWarnings(PHPMD.UnusedPrivateMethod)
      */
-    private function sortInherited($a, $b)
+    private function sortInherited($current, $next)
     {
-        if ($a['inheritance_level'] > $b['inheritance_level']) {
+        if ($current['inheritance_level'] > $next['inheritance_level']) {
             return -1;
-        }
-        if ($a['inheritance_level'] < $b['inheritance_level']) {
+        } elseif ($current['inheritance_level'] < $next['inheritance_level']) {
             return 1;
         }
-        if ($a['sort_order'] > $b['sort_order']) {
+        if ($current['sort_order'] > $next['sort_order']) {
             return 1;
-        }
-        if ($a['sort_order'] < $b['sort_order']) {
+        } elseif ($current['sort_order'] < $next['sort_order']) {
             return -1;
         }
         return 0;
@@ -239,12 +157,12 @@ class Dictionary
      * The files are sorted alphabetically, then each of them is read, and results are recorded into key => value array
      *
      * @param string $vendor
-     * @param string $code
+     * @param string $package
      * @return array
      */
-    private function readPackCsv($vendor, $code)
+    private function readPackCsv($vendor, $package)
     {
-        $files = $this->dir->search("{$vendor}/{$code}/*.csv");
+        $files = $this->dir->search("{$vendor}/{$package}/*.csv");
         sort($files);
         $result = [];
         foreach ($files as $path) {
diff --git a/lib/internal/Magento/Framework/App/Language/package.xsd b/lib/internal/Magento/Framework/App/Language/package.xsd
index 8eb7aa87c5e5de0391906614a17bc63e99407d5e..3f3e33a182be072b7c33d7ee26bf11d8708b1679 100644
--- a/lib/internal/Magento/Framework/App/Language/package.xsd
+++ b/lib/internal/Magento/Framework/App/Language/package.xsd
@@ -24,7 +24,13 @@
  */
 -->
 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
-    <xs:element name="language" type="languageDeclarationType"/>
+    <xs:element name="language" type="languageDeclarationType">
+        <xs:unique name="vendorCode">
+            <xs:selector xpath="use"/>
+            <xs:field xpath="@vendor"/>
+            <xs:field xpath="@package"/>
+        </xs:unique>
+    </xs:element>
 
     <xs:complexType name="languageDeclarationType">
         <xs:annotation>
@@ -33,8 +39,9 @@
         <xs:sequence>
             <xs:element minOccurs="1" maxOccurs="1" name="code" type="codeType"/>
             <xs:element minOccurs="1" maxOccurs="1" name="vendor" type="vendorType"/>
+            <xs:element minOccurs="1" maxOccurs="1" name="package" type="packageType"/>
             <xs:element minOccurs="0" maxOccurs="1" name="sort_order" type="xs:integer"/>
-            <xs:element minOccurs="0" maxOccurs="1" name="use" type="useType"/>
+            <xs:element minOccurs="0" maxOccurs="unbounded" name="use" type="useType"/>
         </xs:sequence>
     </xs:complexType>
 
@@ -46,12 +53,18 @@
 
     <xs:simpleType name="vendorType">
         <xs:restriction base="xs:string">
-            <xs:pattern value="[A-Z][A-Za-z]+"/>
+            <xs:pattern value="[a-z\-_]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="packageType">
+        <xs:restriction base="xs:string">
+            <xs:pattern value="[a-z\-_]+"/>
         </xs:restriction>
     </xs:simpleType>
 
     <xs:complexType name="useType">
         <xs:attribute use="required" name="vendor" type="vendorType"/>
-        <xs:attribute use="required" name="code" type="codeType"/>
+        <xs:attribute use="required" name="package" type="packageType"/>
     </xs:complexType>
 </xs:schema>
diff --git a/lib/internal/Magento/Framework/App/Resource.php b/lib/internal/Magento/Framework/App/Resource.php
index 9cc0704240ae3badc9d2c8c1145bd59d47aee9aa..bdb1f8ffbfe439f5a305d88ec091818161643519 100644
--- a/lib/internal/Magento/Framework/App/Resource.php
+++ b/lib/internal/Magento/Framework/App/Resource.php
@@ -40,6 +40,8 @@ class Resource
 
     const DEFAULT_READ_RESOURCE = 'core_read';
 
+    const DEFAULT_WRITE_RESOURCE = 'core_write';
+
     /**
      * Instances of actual connections
      *
diff --git a/lib/internal/Magento/Framework/AppInterface.php b/lib/internal/Magento/Framework/AppInterface.php
index a51c3246ce9ea94ad37dee28bf1893c2f28e2975..14cdde47f814fc543dbf6cddf0664e75957d52d3 100644
--- a/lib/internal/Magento/Framework/AppInterface.php
+++ b/lib/internal/Magento/Framework/AppInterface.php
@@ -35,7 +35,7 @@ interface AppInterface
     /**
      * Magento version
      */
-    const VERSION = '2.0.0.0-dev87';
+    const VERSION = '2.0.0.0-dev88';
 
     /**
      * Launch application
diff --git a/lib/internal/Magento/Framework/Data/Tree/Node.php b/lib/internal/Magento/Framework/Data/Tree/Node.php
index 0e3db60102a8f44fbc18dc54748856f7a3d3cb4f..ec8591aa17437946da25c1f930af1dee46b07fda 100644
--- a/lib/internal/Magento/Framework/Data/Tree/Node.php
+++ b/lib/internal/Magento/Framework/Data/Tree/Node.php
@@ -65,15 +65,15 @@ class Node extends \Magento\Framework\Object
      * Data tree node constructor
      *
      * @param array $data
-     * @param string $idFeild
+     * @param string $idField
      * @param Tree $tree
      * @param Node $parent
      */
-    public function __construct($data, $idFeild, $tree, $parent = null)
+    public function __construct($data, $idField, $tree, $parent = null)
     {
         $this->setTree($tree);
         $this->setParent($parent);
-        $this->setIdField($idFeild);
+        $this->setIdField($idField);
         $this->setData($data);
         $this->_childNodes = new Collection($this);
     }
diff --git a/lib/internal/Magento/Framework/Data/Tree/Node/Collection.php b/lib/internal/Magento/Framework/Data/Tree/Node/Collection.php
index 6242a0963b4b4bdf4062d6ba7f3f2eccf401d82e..68ff413299dc0c9e4c7638560fde8a5f15574698 100644
--- a/lib/internal/Magento/Framework/Data/Tree/Node/Collection.php
+++ b/lib/internal/Magento/Framework/Data/Tree/Node/Collection.php
@@ -165,7 +165,14 @@ class Collection implements \ArrayAccess, \IteratorAggregate
      */
     public function lastNode()
     {
-        return !empty($this->_nodes) ? $this->_nodes[count($this->_nodes) - 1] : null;
+        if (!empty($this->_nodes)) {
+            $result = end($this->_nodes);
+            reset($this->_nodes);
+        } else {
+            $result = null;
+        }
+
+        return $result;
     }
 
     /**
diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/File.php b/lib/internal/Magento/Framework/Filesystem/Driver/File.php
index b86ae711736677db017f73a90bdb6b85f2315c95..8fb3a6505dcbfe6afbf3b099898fe585a2ad9b4c 100644
--- a/lib/internal/Magento/Framework/Filesystem/Driver/File.php
+++ b/lib/internal/Magento/Framework/Filesystem/Driver/File.php
@@ -239,17 +239,7 @@ class File implements DriverInterface
         clearstatcache();
         $globPattern = rtrim($path, '/') . '/' . ltrim($pattern, '/');
         $result = @glob($globPattern, GLOB_BRACE);
-        if ($result === false) {
-            throw new FilesystemException(
-                sprintf(
-                    'The "%s" pattern cannot be processed in "%s" path %s',
-                    $pattern,
-                    $path,
-                    $this->getWarningMessage()
-                )
-            );
-        }
-        return $result;
+        return is_array($result) ? $result : [];
     }
 
     /**
diff --git a/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php b/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php
index 7230f00131f1d7d14761a2a3d2dae5d357dec06b..ea9837ef99d2848af53d34feee6508e6af8ba957 100644
--- a/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php
+++ b/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php
@@ -197,7 +197,9 @@ class Curl implements \Zend_Http_Client_Adapter_Interface
         $response = curl_exec($this->_getResource());
 
         // Remove 100 and 101 responses headers
-        if (\Zend_Http_Response::extractCode($response) == 100 || \Zend_Http_Response::extractCode($response) == 101) {
+        while (\Zend_Http_Response::extractCode($response) == 100
+            || \Zend_Http_Response::extractCode($response) == 101
+        ) {
             $response = preg_split('/^\r?$/m', $response, 2);
             $response = trim($response[1]);
         }
diff --git a/lib/internal/Magento/Framework/Module/Declaration/FileResolver.php b/lib/internal/Magento/Framework/Module/Declaration/FileResolver.php
index ecc6214f0e7815997fb2555e98013d1afe6d55a6..07fba50d6407dd275116dfd6f19bac86cb70ca4c 100644
--- a/lib/internal/Magento/Framework/Module/Declaration/FileResolver.php
+++ b/lib/internal/Magento/Framework/Module/Declaration/FileResolver.php
@@ -82,13 +82,17 @@ class FileResolver implements \Magento\Framework\Config\FileResolverInterface
         $mageScopePath = $moduleDir . '/Magento';
         $output = array('base' => array(), 'mage' => array(), 'custom' => array());
         $files = glob($moduleDir . '*/*/etc/module.xml');
-        foreach ($files as $file) {
-            $scope = strpos($file, $mageScopePath) === 0 ? 'mage' : 'custom';
-            $output[$scope][] = $this->rootDirectory->getRelativePath($file);
+        if (!empty($files)) {
+            foreach ($files as $file) {
+                $scope = strpos($file, $mageScopePath) === 0 ? 'mage' : 'custom';
+                $output[$scope][] = $this->rootDirectory->getRelativePath($file);
+            }
         }
         $files = glob($configDir . '*/module.xml');
-        foreach ($files as $file) {
-            $output['base'][] = $this->rootDirectory->getRelativePath($file);
+        if (!empty($files)) {
+            foreach ($files as $file) {
+                $output['base'][] = $this->rootDirectory->getRelativePath($file);
+            }
         }
         return $this->iteratorFactory->create(
             $this->rootDirectory,
diff --git a/lib/internal/Magento/Framework/Module/ResourceResolver.php b/lib/internal/Magento/Framework/Module/ResourceResolver.php
index fec05e749f8734d1fd8bd5cb4ba0d9aeb0f0592c..857810be2f3ebd797088bfb8a877ba164793b39f 100644
--- a/lib/internal/Magento/Framework/Module/ResourceResolver.php
+++ b/lib/internal/Magento/Framework/Module/ResourceResolver.php
@@ -61,14 +61,20 @@ class ResourceResolver implements \Magento\Framework\Module\ResourceResolverInte
             // Process sub-directories within modules sql directory
             $moduleSqlDir = $this->_moduleReader->getModuleDir('sql', $moduleName);
             $sqlResources = array();
-            foreach (glob($moduleSqlDir . '/*', GLOB_ONLYDIR) as $resourceDir) {
-                $sqlResources[] = basename($resourceDir);
+            $resourceDirs = glob($moduleSqlDir . '/*', GLOB_ONLYDIR);
+            if (!empty($resourceDirs)) {
+                foreach ($resourceDirs as $resourceDir) {
+                    $sqlResources[] = basename($resourceDir);
+                }
             }
             $moduleDataDir = $this->_moduleReader->getModuleDir('data', $moduleName);
             // Process sub-directories within modules data directory
             $dataResources = array();
-            foreach (glob($moduleDataDir . '/*', GLOB_ONLYDIR) as $resourceDir) {
-                $dataResources[] = basename($resourceDir);
+            $resourceDirs = glob($moduleDataDir . '/*', GLOB_ONLYDIR);
+            if (!empty($resourceDirs)) {
+                foreach ($resourceDirs as $resourceDir) {
+                    $dataResources[] = basename($resourceDir);
+                }
             }
             $this->_moduleResources[$moduleName] = array_unique(array_merge($sqlResources, $dataResources));
         }
diff --git a/lib/internal/Magento/Framework/Parse/Zip.php b/lib/internal/Magento/Framework/Parse/Zip.php
new file mode 100644
index 0000000000000000000000000000000000000000..e8c2c9884e0ae92966c36484f8c73dbc7b296c1c
--- /dev/null
+++ b/lib/internal/Magento/Framework/Parse/Zip.php
@@ -0,0 +1,167 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/**
+ * Various methods for parsing Zip codes
+ *
+ */
+namespace Magento\Framework\Parse;
+
+class Zip
+{
+    /**
+     * Retrieve array of regions characterized by provided params
+     *
+     * @param string $state
+     * @param string $zip
+     * @return string[]
+     */
+    public static function parseRegions($state, $zip)
+    {
+        return !empty($zip) && $zip != '*' ? self::parseZip($zip) : ($state ? array($state) : array('*'));
+    }
+
+    /**
+     * Retrieve array of regions characterized by provided zip code
+     *
+     * @param string $zip
+     * @return string[]
+     */
+    public static function parseZip($zip)
+    {
+        if (strpos($zip, '-') == -1) {
+            return array($zip);
+        } else {
+            return self::zipRangeToZipPattern($zip);
+        }
+    }
+
+    /**
+     * Convert a Magento zip range to an array of zip patterns
+     * (e.g., 12000-13999 -> [12*, 13*])
+     *
+     * @param  string $zipRange
+     * @return array
+     */
+    public static function zipRangeToZipPattern($zipRange)
+    {
+        $zipLength = 5;
+        $zipPattern = array();
+
+        if (!preg_match("/^(.+)-(.+)$/", $zipRange, $zipParts)) {
+            return array($zipRange);
+        }
+
+        if ($zipParts[1] == $zipParts[2]) {
+            return array($zipParts[1]);
+        }
+
+        if ($zipParts[1] > $zipParts[2]) {
+            list($zipParts[2], $zipParts[1]) = array($zipParts[1], $zipParts[2]);
+        }
+
+        $from = str_split($zipParts[1]);
+        $to = str_split($zipParts[2]);
+
+        $startZip = '';
+        $diffPosition = null;
+        for ($pos = 0; $pos < $zipLength; $pos++) {
+            if ($from[$pos] == $to[$pos]) {
+                $startZip .= $from[$pos];
+            } else {
+                $diffPosition = $pos;
+                break;
+            }
+        }
+
+        /*
+         * calculate zip-patterns
+         */
+        if (min(array_slice($to, $diffPosition)) == 9 && max(array_slice($from, $diffPosition)) == 0) {
+            // particular case like 11000-11999 -> 11*
+            return array($startZip . '*');
+        } else {
+            // calculate approximate zip-patterns
+            $start = $from[$diffPosition];
+            $finish = $to[$diffPosition];
+            if ($diffPosition < $zipLength - 1) {
+                $start++;
+                $finish--;
+            }
+            $end = $diffPosition < $zipLength - 1 ? '*' : '';
+            for ($digit = $start; $digit <= $finish; $digit++) {
+                $zipPattern[] = $startZip . $digit . $end;
+            }
+        }
+
+        if ($diffPosition == $zipLength - 1) {
+            return $zipPattern;
+        }
+
+        $nextAsteriskFrom = true;
+        $nextAsteriskTo = true;
+        for ($pos = $zipLength - 1; $pos > $diffPosition; $pos--) {
+            // calculate zip-patterns based on $from value
+            if ($from[$pos] == 0 && $nextAsteriskFrom) {
+                $nextAsteriskFrom = true;
+            } else {
+                $subZip = '';
+                for ($k = $diffPosition; $k < $pos; $k++) {
+                    $subZip .= $from[$k];
+                }
+                $delta = $nextAsteriskFrom ? 0 : 1;
+                $end = $pos < $zipLength - 1 ? '*' : '';
+                for ($i = $from[$pos] + $delta; $i <= 9; $i++) {
+                    $zipPattern[] = $startZip . $subZip . $i . $end;
+                }
+                $nextAsteriskFrom = false;
+            }
+
+            // calculate zip-patterns based on $to value
+            if ($to[$pos] == 9 && $nextAsteriskTo) {
+                $nextAsteriskTo = true;
+            } else {
+                $subZip = '';
+                for ($k = $diffPosition; $k < $pos; $k++) {
+                    $subZip .= $to[$k];
+                }
+                $delta = $nextAsteriskTo ? 0 : 1;
+                $end = $pos < $zipLength - 1 ? '*' : '';
+                for ($i = 0; $i <= $to[$pos] - $delta; $i++) {
+                    $zipPattern[] = $startZip . $subZip . $i . $end;
+                }
+                $nextAsteriskTo = false;
+            }
+        }
+
+        if ($nextAsteriskFrom) {
+            $zipPattern[] = $startZip . $from[$diffPosition] . '*';
+        }
+        if ($nextAsteriskTo) {
+            $zipPattern[] = $startZip . $to[$diffPosition] . '*';
+        }
+
+        return $zipPattern;
+    }
+}
diff --git a/lib/internal/Magento/Framework/Phrase/Renderer/Translate.php b/lib/internal/Magento/Framework/Phrase/Renderer/Translate.php
index 58be776147f542259a5ed04679dd88d97d510b97..9eae2cc21a3ff0054c5015380727e7fae16e79d8 100644
--- a/lib/internal/Magento/Framework/Phrase/Renderer/Translate.php
+++ b/lib/internal/Magento/Framework/Phrase/Renderer/Translate.php
@@ -53,17 +53,8 @@ class Translate implements \Magento\Framework\Phrase\RendererInterface
     {
         $text = end($source);
 
-        $code = $this->translator->getTheme() . '::' . $text;
-
         $data = $this->translator->getData();
 
-        if (array_key_exists($code, $data)) {
-            return $data[$code];
-        }
-        if (array_key_exists($text, $data)) {
-            return $data[$text];
-        }
-
-        return $text;
+        return array_key_exists($text, $data) ? $data[$text] : $text;
     }
 }
diff --git a/lib/internal/Magento/Framework/Simplexml/Config.php b/lib/internal/Magento/Framework/Simplexml/Config.php
index 3e56edf2f43c01a9d713b629542c87174b79244a..64f071b6dddd9d0a63dd70e521d1f89d0a153d29 100644
--- a/lib/internal/Magento/Framework/Simplexml/Config.php
+++ b/lib/internal/Magento/Framework/Simplexml/Config.php
@@ -31,7 +31,7 @@ class Config
     /**
      * Configuration xml
      *
-     * @var \Magento\Framework\Simplexml\Element
+     * @var Element
      */
     protected $_xml = null;
 
@@ -73,7 +73,7 @@ class Config
     /**
      * Cache resource object
      *
-     * @var \Magento\Framework\Simplexml\Config\Cache\AbstractCache
+     * @var Config\Cache\AbstractCache
      */
     protected $_cache = null;
 
@@ -96,15 +96,15 @@ class Config
      *
      * Initializes XML for this configuration
      *
-     * @see self::setXml
-     * @param string|\Magento\Framework\Simplexml\Element $sourceData
+     * @see \Magento\Framework\Simplexml\Config::setXml
+     * @param string|Element $sourceData
      */
     public function __construct($sourceData = null)
     {
-        if (is_null($sourceData)) {
+        if ($sourceData === null) {
             return;
         }
-        if ($sourceData instanceof \Magento\Framework\Simplexml\Element) {
+        if ($sourceData instanceof Element) {
             $this->setXml($sourceData);
         } elseif (is_string($sourceData) && !empty($sourceData)) {
             if (strlen($sourceData) < 1000 && is_readable($sourceData)) {
@@ -118,10 +118,10 @@ class Config
     /**
      * Sets xml for this configuration
      *
-     * @param \Magento\Framework\Simplexml\Element $node
+     * @param Element $node
      * @return $this
      */
-    public function setXml(\Magento\Framework\Simplexml\Element $node)
+    public function setXml(Element $node)
     {
         $this->_xml = $node;
         return $this;
@@ -130,13 +130,13 @@ class Config
     /**
      * Returns node found by the $path
      *
-     * @see     \Magento\Framework\Simplexml\Element::descend
-     * @param   string $path
-     * @return  \Magento\Framework\Simplexml\Element|bool
+     * @see \Magento\Framework\Simplexml\Element::descend
+     * @param string $path
+     * @return Element|bool
      */
     public function getNode($path = null)
     {
-        if (!$this->_xml instanceof \Magento\Framework\Simplexml\Element) {
+        if (!$this->_xml instanceof Element) {
             return false;
         } elseif ($path === null) {
             return $this->_xml;
@@ -149,7 +149,7 @@ class Config
      * Returns nodes found by xpath expression
      *
      * @param string $xpath
-     * @return \SimpleXMLElement[]|bool
+     * @return Element[]|bool
      */
     public function getXpath($xpath)
     {
@@ -167,7 +167,7 @@ class Config
     /**
      * Enter description here...
      *
-     * @param \Magento\Framework\Simplexml\Config\Cache\AbstractCache $cache
+     * @param Config\Cache\AbstractCache $cache
      * @return $this
      */
     public function setCache($cache)
@@ -179,7 +179,7 @@ class Config
     /**
      * Enter description here...
      *
-     * @return \Magento\Framework\Simplexml\Config\Cache\AbstractCache
+     * @return Config\Cache\AbstractCache
      */
     public function getCache()
     {
@@ -282,7 +282,7 @@ class Config
      */
     public function setCacheChecksum($data)
     {
-        if (is_null($data)) {
+        if ($data === null) {
             $this->_cacheChecksum = null;
         } elseif (false === $data || 0 === $data) {
             $this->_cacheChecksum = false;
@@ -352,7 +352,7 @@ class Config
         if (false === $newChecksum) {
             return false;
         }
-        if (is_null($newChecksum)) {
+        if ($newChecksum === null) {
             return true;
         }
         $cachedChecksum = $this->getCache()->load($this->getCacheChecksumId());
@@ -371,9 +371,7 @@ class Config
         }
 
         $xmlString = $this->_loadCache($this->getCacheId());
-        $xml = simplexml_load_string($xmlString, $this->_elementClass);
-        if ($xml) {
-            $this->_xml = $xml;
+        if ($this->loadString($xmlString)) {
             $this->setCacheSaved(true);
             return true;
         }
@@ -389,29 +387,19 @@ class Config
      */
     public function saveCache($tags = null)
     {
-        if ($this->getCacheSaved()) {
-            return $this;
-        }
-        if (false === $this->getCacheChecksum()) {
+        if ($this->getCacheSaved() || $this->getCacheChecksum() === false) {
             return $this;
         }
 
-        if (is_null($tags)) {
-            $tags = $this->_cacheTags;
+        if ($tags === null) {
+            $tags = $this->getCacheTags();
         }
 
-        if (!is_null($this->getCacheChecksum())) {
-            $this->_saveCache(
-                $this->getCacheChecksum(),
-                $this->getCacheChecksumId(),
-                $tags,
-                $this->getCacheLifetime()
-            );
+        if ($this->getCacheChecksum() === null) {
+            $this->_saveCache($this->getCacheChecksum(), $this->getCacheChecksumId(), $tags, $this->getCacheLifetime());
         }
 
-        $xmlString = $this->getXmlString();
-        $this->_saveCache($xmlString, $this->getCacheId(), $tags, $this->getCacheLifetime());
-
+        $this->_saveCache($this->getXmlString(), $this->getCacheId(), $tags, $this->getCacheLifetime());
         $this->setCacheSaved(true);
 
         return $this;
@@ -491,7 +479,7 @@ class Config
 
         $fileData = file_get_contents($filePath);
         $fileData = $this->processFileData($fileData);
-        return $this->loadString($fileData, $this->_elementClass);
+        return $this->loadString($fileData);
     }
 
     /**
@@ -504,7 +492,7 @@ class Config
     {
         if (!empty($string)) {
             $xml = simplexml_load_string($string, $this->_elementClass);
-            if ($xml instanceof \Magento\Framework\Simplexml\Element) {
+            if ($xml) {
                 $this->_xml = $xml;
                 return true;
             }
@@ -540,7 +528,7 @@ class Config
      */
     public function setNode($path, $value, $overwrite = true)
     {
-        $xml = $this->_xml->setNode($path, $value, $overwrite);
+        $this->_xml->setNode($path, $value, $overwrite);
         return $this;
     }
 
@@ -555,7 +543,6 @@ class Config
         if (!$targets) {
             return $this;
         }
-
         foreach ($targets as $target) {
             $sources = $this->getXpath((string)$target['extends']);
             if ($sources) {
@@ -584,11 +571,11 @@ class Config
     /**
      * Enter description here...
      *
-     * @param \Magento\Framework\Simplexml\Config $config
+     * @param Config $config
      * @param boolean $overwrite
      * @return $this
      */
-    public function extend(\Magento\Framework\Simplexml\Config $config, $overwrite = true)
+    public function extend(Config $config, $overwrite = true)
     {
         $this->getNode()->extend($config->getNode(), $overwrite);
         return $this;
diff --git a/lib/internal/Magento/Framework/Simplexml/Config/Cache/AbstractCache.php b/lib/internal/Magento/Framework/Simplexml/Config/Cache/AbstractCache.php
index a423f4a68c5ca567ac9c4b28bca7345626bee643..7ec8e191b0609adefee753e28ad4bd1b20cfa796 100644
--- a/lib/internal/Magento/Framework/Simplexml/Config/Cache/AbstractCache.php
+++ b/lib/internal/Magento/Framework/Simplexml/Config/Cache/AbstractCache.php
@@ -26,12 +26,15 @@ namespace Magento\Framework\Simplexml\Config\Cache;
 
 /**
  * Abstract class for configuration cache
+ * @method void setComponents(array $components)
+ * @method void setIsAllowedToSave(bool $isAllowedToSave)
+ * @method array getComponents()
  */
 abstract class AbstractCache extends \Magento\Framework\Object
 {
     /**
      * Constructor
-     * 
+     *
      * Initializes components and allows to save the cache
      *
      * @param array $data
@@ -72,7 +75,7 @@ abstract class AbstractCache extends \Magento\Framework\Object
         if (empty($data) || !is_array($data)) {
             return false;
         }
-        // check that no source files were changed or check file exsists
+        // check that no source files were changed or check file exists
         foreach ($data as $sourceFile => $stat) {
             if (empty($stat['mtime']) || !is_file($sourceFile) || filemtime($sourceFile) !== $stat['mtime']) {
                 return false;
@@ -93,4 +96,14 @@ abstract class AbstractCache extends \Magento\Framework\Object
         $hash = md5($sum);
         return $hash;
     }
+
+    /**
+     * @return bool
+     */
+    abstract public function load();
+
+    /**
+     * @return bool
+     */
+    abstract public function save();
 }
diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/DateTime.php b/lib/internal/Magento/Framework/Stdlib/DateTime/DateTime.php
index 938a79672962bdad837547bf70fdbaa55c8271cd..92b1f1e35ffb176b556f709017abaae644706cdb 100644
--- a/lib/internal/Magento/Framework/Stdlib/DateTime/DateTime.php
+++ b/lib/internal/Magento/Framework/Stdlib/DateTime/DateTime.php
@@ -21,13 +21,14 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
+
+namespace Magento\Framework\Stdlib\DateTime;
+
 /**
  * Date conversion model
  *
- * @author      Magento Core Team <core@magentocommerce.com>
+ * @author Magento Core Team <core@magentocommerce.com>
  */
-namespace Magento\Framework\Stdlib\DateTime;
-
 class DateTime
 {
     /**
@@ -38,14 +39,14 @@ class DateTime
     private $_offset = 0;
 
     /**
-     * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface
+     * @var TimezoneInterface
      */
     protected $_localeDate;
 
     /**
-     * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
+     * @param TimezoneInterface $localeDate
      */
-    public function __construct(\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate)
+    public function __construct(TimezoneInterface $localeDate)
     {
         $this->_localeDate = $localeDate;
         $this->_offset = $this->calculateOffset($this->_localeDate->getConfigTimezone());
@@ -61,15 +62,15 @@ class DateTime
     {
         $result = true;
         $offset = 0;
-        if (!is_null($timezone)) {
-            $oldzone = @date_default_timezone_get();
+        if ($timezone !== null) {
+            $oldZone = @date_default_timezone_get();
             $result = date_default_timezone_set($timezone);
         }
         if ($result === true) {
             $offset = gmmktime(0, 0, 0, 1, 2, 1970) - mktime(0, 0, 0, 1, 2, 1970);
         }
-        if (!is_null($timezone)) {
-            date_default_timezone_set($oldzone);
+        if ($timezone !== null) {
+            date_default_timezone_set($oldZone);
         }
         return $offset;
     }
@@ -83,7 +84,7 @@ class DateTime
      */
     public function gmtDate($format = null, $input = null)
     {
-        if (is_null($format)) {
+        if ($format === null) {
             $format = 'Y-m-d H:i:s';
         }
         $date = $this->gmtTimestamp($input);
@@ -104,7 +105,7 @@ class DateTime
      */
     public function date($format = null, $input = null)
     {
-        if (is_null($format)) {
+        if ($format === null) {
             $format = 'Y-m-d H:i:s';
         }
         $result = date($format, $this->timestamp($input));
@@ -119,14 +120,12 @@ class DateTime
      */
     public function gmtTimestamp($input = null)
     {
-        if (is_null($input)) {
+        if ($input === null) {
             return gmdate('U');
+        } elseif (is_numeric($input)) {
+            $result = $input;
         } else {
-            if (is_numeric($input)) {
-                $result = $input;
-            } else {
-                $result = strtotime($input);
-            }
+            $result = strtotime($input);
         }
         if ($result === false) {
             // strtotime() unable to parse string (it's not a date or has incorrect format)
@@ -147,14 +146,12 @@ class DateTime
      */
     public function timestamp($input = null)
     {
-        if (is_null($input)) {
+        if ($input === null) {
             $result = $this->gmtTimestamp();
+        } elseif (is_numeric($input)) {
+            $result = $input;
         } else {
-            if (is_numeric($input)) {
-                $result = $input;
-            } else {
-                $result = strtotime($input);
-            }
+            $result = strtotime($input);
         }
         $date = $this->_localeDate->date($result);
         $timestamp = $date->get(\Zend_Date::TIMESTAMP) + $date->get(\Zend_Date::TIMEZONE_SECS);
diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php
index eb8a3a4ed755fbfe8f6cd05f1b5cdde9dc091c8e..5e611157f0311c9a5d89640949232e0751b3f853 100644
--- a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php
+++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php
@@ -54,7 +54,7 @@ class Timezone implements TimezoneInterface
     protected $_dateTime;
 
     /**
-     * @var \Magento\Framework\Stdlib\DateTime\DateFactory
+     * @var DateFactory
      */
     protected $_dateFactory;
 
@@ -72,7 +72,7 @@ class Timezone implements TimezoneInterface
      * @param \Magento\Framework\App\ScopeResolverInterface $scopeResolver
      * @param \Magento\Framework\Locale\ResolverInterface $localeResolver
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
-     * @param \Magento\Framework\Stdlib\DateTime\DateFactory $dateFactory
+     * @param DateFactory $dateFactory
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param string $scopeType
      * @param string $defaultTimezonePath
@@ -198,20 +198,17 @@ class Timezone implements TimezoneInterface
     /**
      * {@inheritdoc}
      */
-    public function formatDate(
-        $date = null,
-        $format = \Magento\Framework\Stdlib\DateTime\TimezoneInterface::FORMAT_TYPE_SHORT,
-        $showTime = false
-    ) {
+    public function formatDate($date = null, $format = TimezoneInterface::FORMAT_TYPE_SHORT, $showTime = false)
+    {
         if (!in_array($format, $this->_allowedFormats, true)) {
             return $date;
         }
-        if (!$date instanceof \Magento\Framework\Stdlib\DateTime\DateInterface && $date && !strtotime($date)) {
+        if (!$date instanceof DateInterface && $date && !strtotime($date)) {
             return '';
         }
         if (is_null($date)) {
             $date = $this->date(gmdate('U'), null, null);
-        } elseif (!$date instanceof \Magento\Framework\Stdlib\DateTime\DateInterface) {
+        } elseif (!$date instanceof DateInterface) {
             $date = $this->date(strtotime($date), null, null);
         }
 
@@ -227,11 +224,8 @@ class Timezone implements TimezoneInterface
     /**
      * {@inheritdoc}
      */
-    public function formatTime(
-        $time = null,
-        $format = \Magento\Framework\Stdlib\DateTime\TimezoneInterface::FORMAT_TYPE_SHORT,
-        $showDate = false
-    ) {
+    public function formatTime($time = null, $format = TimezoneInterface::FORMAT_TYPE_SHORT, $showDate = false)
+    {
         if (!in_array($format, $this->_allowedFormats, true)) {
             return $time;
         }
@@ -304,11 +298,11 @@ class Timezone implements TimezoneInterface
     }
 
     /**
-     * Returns a localized information string, supported are several types of informations.
+     * Returns a localized information string, supported are several types of information.
      * For detailed information about the types look into the documentation
      *
-     * @param  string             $value  Name to get detailed information about
-     * @param  string             $path   (Optional) Type of information to return
+     * @param string $value Name to get detailed information about
+     * @param string $path (Optional) Type of information to return
      * @return string|false The wished information in the given language
      */
     protected function _getTranslation($value = null, $path = null)
diff --git a/lib/internal/Magento/Framework/Stdlib/String.php b/lib/internal/Magento/Framework/Stdlib/String.php
index 3b3a0840242b05f59479519ae4e2e2be09bde9c1..852bf99d3b1f5e56906b4d13bc65afd019c434c1 100644
--- a/lib/internal/Magento/Framework/Stdlib/String.php
+++ b/lib/internal/Magento/Framework/Stdlib/String.php
@@ -62,14 +62,8 @@ class String
         foreach ($str as $part) {
             if ($this->strlen($part) >= $length) {
                 $lastDelimiter = $this->strpos($this->strrev($part), $needle);
-                $tmpNewStr = $this->substr(
-                    $this->strrev($part),
-                    0,
-                    $lastDelimiter
-                ) . $insert . $this->substr(
-                    $this->strrev($part),
-                    $lastDelimiter
-                );
+                $tmpNewStr = $this->substr($this->strrev($part), 0, $lastDelimiter) . $insert
+                    . $this->substr($this->strrev($part), $lastDelimiter);
                 $newStr .= $this->strrev($tmpNewStr);
             } else {
                 $newStr .= $part;
diff --git a/lib/internal/Magento/Framework/Translate.php b/lib/internal/Magento/Framework/Translate.php
index 6dd0d97c7a04e1470579e0f868ac2d51e0103ed2..1bc59d063528e29c5f0f852478e604718733155d 100644
--- a/lib/internal/Magento/Framework/Translate.php
+++ b/lib/internal/Magento/Framework/Translate.php
@@ -59,13 +59,6 @@ class Translate implements \Magento\Framework\TranslateInterface
      */
     protected $_data = [];
 
-    /**
-     * Translation data for data scope (per module)
-     *
-     * @var array
-     */
-    protected $_dataScope;
-
     /**
      * @var \Magento\Framework\View\DesignInterface
      */
@@ -199,10 +192,10 @@ class Translate implements \Magento\Framework\TranslateInterface
         }
         $this->_data = [];
 
-        $this->_loadModuleTranslation($forceReload);
-        $this->_loadThemeTranslation($forceReload);
-        $this->_loadPackTranslation($forceReload);
-        $this->_loadDbTranslation($forceReload);
+        $this->_loadModuleTranslation();
+        $this->_loadThemeTranslation();
+        $this->_loadPackTranslation();
+        $this->_loadDbTranslation();
 
         if (!$forceReload) {
             $this->_saveCache();
@@ -260,14 +253,13 @@ class Translate implements \Magento\Framework\TranslateInterface
     /**
      * Load data from module translation files
      *
-     * @param bool $forceReload
      * @return $this
      */
-    protected function _loadModuleTranslation($forceReload = false)
+    protected function _loadModuleTranslation()
     {
         foreach ($this->_moduleList->getModules() as $module) {
             $moduleFilePath = $this->_getModuleTranslationFile($module['name'], $this->getLocale());
-            $this->_addData($this->_getFileData($moduleFilePath), false, $forceReload);
+            $this->_addData($this->_getFileData($moduleFilePath));
         }
         return $this;
     }
@@ -276,11 +268,9 @@ class Translate implements \Magento\Framework\TranslateInterface
      * Adding translation data
      *
      * @param array $data
-     * @param string|bool $scope
-     * @param boolean $forceReload
      * @return $this
      */
-    protected function _addData($data, $scope = false, $forceReload = false)
+    protected function _addData($data)
     {
         foreach ($data as $key => $value) {
             if ($key === $value) {
@@ -290,23 +280,7 @@ class Translate implements \Magento\Framework\TranslateInterface
             $key = str_replace('""', '"', $key);
             $value  = str_replace('""', '"', $value);
 
-            if ($scope && isset($this->_dataScope[$key]) && !$forceReload) {
-                /**
-                 * Checking previous value
-                 */
-                $scopeKey = $this->_dataScope[$key] . '::' . $key;
-                if (!isset($this->_data[$scopeKey])) {
-                    if (isset($this->_data[$key])) {
-                        $this->_data[$scopeKey] = $this->_data[$key];
-                        unset($this->_data[$key]);
-                    }
-                }
-                $scopeKey = $scope . '::' . $key;
-                $this->_data[$scopeKey] = $value;
-            } else {
-                $this->_data[$key] = $value;
-                $this->_dataScope[$key] = $scope;
-            }
+            $this->_data[$key] = $value;
         }
         return $this;
     }
@@ -314,10 +288,9 @@ class Translate implements \Magento\Framework\TranslateInterface
     /**
      * Load current theme translation
      *
-     * @param bool $forceReload
      * @return $this
      */
-    protected function _loadThemeTranslation($forceReload = false)
+    protected function _loadThemeTranslation()
     {
         if (!$this->_config['theme']) {
             return $this;
@@ -325,7 +298,7 @@ class Translate implements \Magento\Framework\TranslateInterface
 
         $file = $this->_getThemeTranslationFile($this->getLocale());
         if ($file) {
-            $this->_addData($this->_getFileData($file), 'theme' . $this->_config['theme'], $forceReload);
+            $this->_addData($this->_getFileData($file));
         }
         return $this;
     }
@@ -333,25 +306,23 @@ class Translate implements \Magento\Framework\TranslateInterface
     /**
      * Load translation dictionary from language packages
      *
-     * @param bool $forceReload
      * @return void
      */
-    protected function _loadPackTranslation($forceReload = false)
+    protected function _loadPackTranslation()
     {
         $data = $this->packDictionary->getDictionary($this->getLocale());
-        $this->_addData($data, 'language_pack', $forceReload);
+        $this->_addData($data);
     }
 
     /**
      * Loading current translation from DB
      *
-     * @param bool $forceReload
      * @return $this
      */
-    protected function _loadDbTranslation($forceReload = false)
+    protected function _loadDbTranslation()
     {
-        $arr = $this->_translateResource->getTranslationArray(null, $this->getLocale());
-        $this->_addData($arr, $this->getConfig('scope'), $forceReload);
+        $data = $this->_translateResource->getTranslationArray(null, $this->getLocale());
+        $this->_addData($data);
         return $this;
     }
 
diff --git a/lib/internal/Magento/Framework/View/BlockPool.php b/lib/internal/Magento/Framework/View/BlockPool.php
index 4304fc712e1f815f08819e823f26fb2864749609..836d6a6cd7bb249c46011176ff9fb56921300e4a 100644
--- a/lib/internal/Magento/Framework/View/BlockPool.php
+++ b/lib/internal/Magento/Framework/View/BlockPool.php
@@ -49,12 +49,10 @@ class BlockPool
     /**
      * Constructor
      *
-     * @param ObjectManager $objectManager
      * @param BlockFactory $blockFactory
      */
-    public function __construct(ObjectManager $objectManager, BlockFactory $blockFactory)
+    public function __construct(BlockFactory $blockFactory)
     {
-        $this->objectManager = $objectManager;
         $this->blockFactory = $blockFactory;
     }
 
diff --git a/lib/internal/Magento/Framework/View/Config.php b/lib/internal/Magento/Framework/View/Config.php
index 3a89069eb38f4ce0e65b33f53272ed0aedcce6b0..4550ec84ed4ec43215b668bed544e8e6191308c8 100644
--- a/lib/internal/Magento/Framework/View/Config.php
+++ b/lib/internal/Magento/Framework/View/Config.php
@@ -123,17 +123,15 @@ class Config implements \Magento\Framework\View\ConfigInterface
 
         $configFiles = $this->moduleReader->getConfigurationFiles(basename($this->filename))->toArray();
         $themeConfigFile = $currentTheme->getCustomization()->getCustomViewConfigPath();
-        if (empty($themeConfigFile) || !$this->rootDirectory->isExist(
-            $this->rootDirectory->getRelativePath($themeConfigFile)
-        )
+        if (empty($themeConfigFile)
+            || !$this->rootDirectory->isExist($this->rootDirectory->getRelativePath($themeConfigFile))
         ) {
             $themeConfigFile = $this->viewFileSystem->getFilename($this->filename, $params);
         }
-        if ($themeConfigFile && $this->rootDirectory->isExist($this->rootDirectory->getRelativePath($themeConfigFile))
+        if ($themeConfigFile
+            && $this->rootDirectory->isExist($this->rootDirectory->getRelativePath($themeConfigFile))
         ) {
-            $configFiles[$this->rootDirectory->getRelativePath(
-                $themeConfigFile
-            )] = $this->rootDirectory->readFile(
+            $configFiles[$this->rootDirectory->getRelativePath($themeConfigFile)] = $this->rootDirectory->readFile(
                 $this->rootDirectory->getRelativePath($themeConfigFile)
             );
         }
diff --git a/lib/internal/Magento/Framework/View/DataSourcePool.php b/lib/internal/Magento/Framework/View/DataSourcePool.php
index c7816c71eace7c66f5bcf83b1ffe82649bf66613..853bc8ccc7ac3c7640835b3bfda701a58a340ddc 100644
--- a/lib/internal/Magento/Framework/View/DataSourcePool.php
+++ b/lib/internal/Magento/Framework/View/DataSourcePool.php
@@ -74,7 +74,7 @@ class DataSourcePool
         if (!isset($this->dataSources[$name])) {
 
             if (!class_exists($class)) {
-                throw new \Exception(__('Invalid Data Source class name: ' . $class));
+                throw new \InvalidArgumentException(__('Invalid Data Source class name: ' . $class));
             }
 
             $data = $this->blockFactory->createBlock($class);
diff --git a/lib/internal/Magento/Framework/View/Element/Html/Link.php b/lib/internal/Magento/Framework/View/Element/Html/Link.php
index a43e5a7310ed1fe7772c6c26318484f21bab4241..4d20cd83789ef705f0c309fa25de1a0a6925a851 100644
--- a/lib/internal/Magento/Framework/View/Element/Html/Link.php
+++ b/lib/internal/Magento/Framework/View/Element/Html/Link.php
@@ -32,6 +32,40 @@ namespace Magento\Framework\View\Element\Html;
  */
 class Link extends \Magento\Framework\View\Element\Template
 {
+    /**
+     * @var array
+     */
+    protected $allowedAttributes = [
+        'href',
+        'title',
+        'charset',
+        'name',
+        'hreflang',
+        'rel',
+        'rev',
+        'accesskey',
+        'shape',
+        'coords',
+        'tabindex',
+        'onfocus',
+        'onblur', // %attrs
+        'id',
+        'class',
+        'style', // %coreattrs
+        'lang',
+        'dir', // %i18n
+        'onclick',
+        'ondblclick',
+        'onmousedown',
+        'onmouseup',
+        'onmouseover',
+        'onmousemove',
+        'onmouseout',
+        'onkeypress',
+        'onkeydown',
+        'onkeyup' // %events
+    ];
+
     /**
      * Prepare link attributes as serialized and formatted string
      *
@@ -39,39 +73,8 @@ class Link extends \Magento\Framework\View\Element\Template
      */
     public function getLinkAttributes()
     {
-        $allow = array(
-            'href',
-            'title',
-            'charset',
-            'name',
-            'hreflang',
-            'rel',
-            'rev',
-            'accesskey',
-            'shape',
-            'coords',
-            'tabindex',
-            'onfocus',
-            'onblur', // %attrs
-            'id',
-            'class',
-            'style', // %coreattrs
-            'lang',
-            'dir', // %i18n
-            'onclick',
-            'ondblclick',
-            'onmousedown',
-            'onmouseup',
-            'onmouseover',
-            'onmousemove',
-            'onmouseout',
-            'onkeypress',
-            'onkeydown',
-            'onkeyup' // %events
-        );
-
         $attributes = array();
-        foreach ($allow as $attribute) {
+        foreach ($this->allowedAttributes as $attribute) {
             $value = $this->getDataUsingMethod($attribute);
             if (!is_null($value)) {
                 $attributes[$attribute] = $this->escapeHtml($value);
diff --git a/lib/internal/Magento/Framework/View/Element/Messages.php b/lib/internal/Magento/Framework/View/Element/Messages.php
index ff69cc22da9064931d0395774cb084870a01f542..a97804ec2de2d5c9d796d2aab120a469c022a495 100644
--- a/lib/internal/Magento/Framework/View/Element/Messages.php
+++ b/lib/internal/Magento/Framework/View/Element/Messages.php
@@ -179,7 +179,7 @@ class Messages extends Template
      * @param MessageInterface $message
      * @return $this
      */
-    public function addMessage(\Magento\Framework\Message\AbstractMessage $message)
+    public function addMessage(MessageInterface $message)
     {
         $this->getMessageCollection()->addMessage($message);
         return $this;
diff --git a/lib/internal/Magento/Framework/View/Layout.php b/lib/internal/Magento/Framework/View/Layout.php
index bc1f5cb3e11b66376c5565a9fb2fe4af1e52dcbf..bb55c22db1266e320f6ae8140debae8dc564756c 100644
--- a/lib/internal/Magento/Framework/View/Layout.php
+++ b/lib/internal/Magento/Framework/View/Layout.php
@@ -110,7 +110,7 @@ class Layout extends \Magento\Framework\Simplexml\Config implements \Magento\Fra
      *
      * @var \Magento\Framework\Object
      */
-    protected $_renderingOutput = null;
+    protected $_renderingOutput;
 
     /**
      * Cache of generated elements' HTML
@@ -1490,14 +1490,14 @@ class Layout extends \Magento\Framework\Simplexml\Config implements \Magento\Fra
      * Get block singleton
      *
      * @param string $type
-     * @throws \Magento\Framework\Model\Exception
      * @return \Magento\Framework\App\Helper\AbstractHelper
+     * @throws \Magento\Framework\Model\Exception
      */
     public function getBlockSingleton($type)
     {
         if (!isset($this->_helpers[$type])) {
             if (!$type) {
-                throw new \Magento\Framework\Model\Exception(__('Invalid block type: %1', $type));
+                throw new \Magento\Framework\Model\Exception('Invalid block type');
             }
 
             $helper = $this->_blockFactory->createBlock($type);
@@ -1532,12 +1532,6 @@ class Layout extends \Magento\Framework\Simplexml\Config implements \Magento\Fra
      */
     public function addAdjustableRenderer($namespace, $staticType, $dynamicType, $type, $template, $data = array())
     {
-        if (!isset($namespace)) {
-            $this->_renderers[$namespace] = array();
-        }
-        if (!isset($namespace)) {
-            $this->_renderers[$namespace][$staticType] = array();
-        }
         $this->_renderers[$namespace][$staticType][$dynamicType] = array(
             'type' => $type,
             'template' => $template,
@@ -1578,18 +1572,11 @@ class Layout extends \Magento\Framework\Simplexml\Config implements \Magento\Fra
         if ($options = $this->getRendererOptions($namespace, $staticType, $dynamicType)) {
             $dictionary = array();
             /** @var $block \Magento\Framework\View\Element\Template */
-            $block = $this->createBlock(
-                $options['type'],
-                ''
-            )->setData(
-                $data
-            )->assign(
-                $dictionary
-            )->setTemplate(
-                $options['template']
-            )->assign(
-                $data
-            );
+            $block = $this->createBlock($options['type'], '')
+                ->setData($data)
+                ->assign($dictionary)
+                ->setTemplate($options['template'])
+                ->assign($data);
 
             echo $this->_renderBlock($block->getNameInLayout());
         }
diff --git a/lib/internal/Magento/Framework/View/LayoutFactory.php b/lib/internal/Magento/Framework/View/LayoutFactory.php
index 13dc969b7cf854961f3e5a675fe547d8fee844f4..d06d3fe114ccf241ec7c8cc64690073168cdeef5 100644
--- a/lib/internal/Magento/Framework/View/LayoutFactory.php
+++ b/lib/internal/Magento/Framework/View/LayoutFactory.php
@@ -61,9 +61,14 @@ class LayoutFactory
      *
      * @param array $data
      * @return LayoutInterface
+     * @throws \InvalidArgumentException
      */
     public function create(array $data = array())
     {
-        return $this->_objectManager->create($this->_instanceName, $data);
+        $layout = $this->_objectManager->create($this->_instanceName, $data);
+        if (!$layout instanceof LayoutInterface) {
+            throw new \InvalidArgumentException(get_class($layout) . ' must be an instance of LayoutInterface.');
+        }
+        return $layout;
     }
 }
diff --git a/lib/internal/Magento/Framework/View/Render/RenderFactory.php b/lib/internal/Magento/Framework/View/Render/RenderFactory.php
index 9d32bd67aadf20ba7b273bb269c514fb7567c672..67dcb382fc069ee784a21c58ee498ce9e11864e1 100644
--- a/lib/internal/Magento/Framework/View/Render/RenderFactory.php
+++ b/lib/internal/Magento/Framework/View/Render/RenderFactory.php
@@ -59,13 +59,11 @@ class RenderFactory
     {
         $className = 'Magento\\Framework\\View\\Render\\' . ucfirst($type);
         $model = $this->objectManager->get($className);
-
-        if ($model instanceof RenderInterface === false) {
+        if (!$model instanceof RenderInterface) {
             throw new \InvalidArgumentException(
-                sprintf('Type "%s" is not instance on Magento\Framework\View\RenderInterface', $type)
+                'Type "' . $type . '" is not instance on Magento\Framework\View\RenderInterface'
             );
         }
-
         return $model;
     }
 }
diff --git a/lib/web/css/docs/source/rating.less b/lib/web/css/docs/source/rating.less
index 83f8acd1755ba9ae0cba89336e784f9b0bede582..42bcc57ea92d1dcde592b4dcf4826c2e65483887 100644
--- a/lib/web/css/docs/source/rating.less
+++ b/lib/web/css/docs/source/rating.less
@@ -24,7 +24,7 @@
 
 //  # Ratings
 //
-//  Ratings styling mixins are based on using font icons as rate symbols. There are two types of ratings: rating which allows user to vote and rating which displays voting results summary. Depending on the rating type mixin <code>.rating-vote()</code> or <code>.rating-summary()</code> is used.
+//  Ratings styling mixins are based on using font icons as rate symbols. There are two types of ratings: rating which allows user to vote and rating which displays voting results summary. Depending on the rating type mixin <code>.mixin-rating-vote()</code> or <code>.mixin-rating-summary()</code> is used.
 //
 //  # Global rating variables
 //
@@ -91,7 +91,7 @@
 
 //  # Rating with vote
 //
-//  To implement rating with vote, use the <code>.rating-vote()</code> mixin.
+//  To implement rating with vote, use the <code>.mixin-rating-vote()</code> mixin.
 //  ``` html
 //  <div class="rating vote example-ratings-1">
 //      <input type="radio" name="rating-price" id="rating-price-1" value="1" />
@@ -118,7 +118,7 @@
 //  ```
 
 .example-ratings-1 {
-    .rating-vote();
+    .mixin-rating-vote();
 }
 
 //  # Rating with vote icons number customization
@@ -163,7 +163,7 @@
 //  ```
 
 .example-ratings-2 {
-    .rating-vote(
+    .mixin-rating-vote(
         @_icon-count: 8
     );
 }
@@ -202,7 +202,7 @@
 //  ```
 
 .example-ratings-3 {
-    .rating-vote(
+    .mixin-rating-vote(
         @_icon-color: #aff5e3,
         @_icon-color-active: #0a6767
     );
@@ -238,7 +238,7 @@
 //  ```
 
 .example-ratings-4 {
-    .rating-vote(
+    .mixin-rating-vote(
         @_icon-content: @icon-wishlist-full
     );
 }
@@ -279,7 +279,7 @@
 
 .exapmle-ratings-5 {
     .control.rating.vote {
-        .rating-vote();
+        .mixin-rating-vote();
     }
 }
 
@@ -289,14 +289,14 @@
 //  ``` html
 //  <div class="example-rating-summary-1">
 //      <span class="label"><span>Rating</span></span>
-//      <div class="rating result" title="60%">
+//      <div class="rating-result" title="60%">
 //          <span style="width:60%"><span>60</span></span>
 //      </div>
 //  </div>
 //  ```
 
 .example-rating-summary-1 {
-    .rating-summary();
+    .mixin-rating-summary();
 }
 
 //  # Rating summary icons number customization
@@ -309,14 +309,14 @@
 //  ``` html
 //  <div class="example-rating-summary-2">
 //      <span class="label"><span>Rating</span></span>
-//      <div class="rating result" title="40%">
+//      <div class="rating-result" title="40%">
 //          <span style="width:40%"><span>40</span></span>
 //      </div>
 //  </div>
 //  ```
 
 .example-rating-summary-2 {
-    .rating-summary(
+    .mixin-rating-summary(
         @_icon-count: 8
     );
 }
@@ -332,14 +332,14 @@
 //  ``` html
 //  <div class="example-rating-summary-3">
 //      <span class="label"><span>Rating</span></span>
-//      <div class="rating result" title="40%">
+//      <div class="rating-result" title="40%">
 //          <span style="width:40%"><span>40</span></span>
 //      </div>
 //  </div>
 //  ```
 
 .example-rating-summary-3 {
-    .rating-summary(
+    .mixin-rating-summary(
         @_icon-color: #aff5e3,
         @_icon-color-active: #0a6767
     );
@@ -355,14 +355,14 @@
 //  ``` html
 //  <div class="example-rating-summary-4">
 //      <span class="label"><span>Rating</span></span>
-//      <div class="rating result" title="40%">
+//      <div class="rating-result" title="40%">
 //          <span style="width:40%"><span>40</span></span>
 //      </div>
 //  </div>
 //  ```
 
 .example-rating-summary-4 {
-    .rating-summary(
+    .mixin-rating-summary(
         @_icon-content: @icon-wishlist-full
     );
 }
@@ -377,14 +377,14 @@
 //  ``` html
 //  <div class="example-rating-summary-5">
 //      <span class="label"><span>Rating</span></span>
-//      <div class="rating result" title="40%">
+//      <div class="rating-result" title="40%">
 //          <span style="width:40%"><span>40</span></span>
 //      </div>
 //  </div>
 //  ```
 
 .example-rating-summary-5 {
-    .rating-summary(
+    .mixin-rating-summary(
         @_label-hide: true
     );
 }
@@ -394,27 +394,27 @@
 //  ``` html
 //  <div class="example-rating-summary-6" tabindex="1">
 //      <strong>Your Rating:</strong>
-//      <div class="rating summary item">
+//      <div class="rating-summary item">
 //          <span class="label"><span>Value</span></span>
-//          <div class="rating result" title="100%" >
+//          <div class="rating-result" title="100%" >
 //              <span style="width:100%"><span>100%</span></span>
 //          </div>
 //      </div>
-//      <div class="rating summary item">
+//      <div class="rating-summary item">
 //          <span class="label"><span>Quality</span></span>
-//          <div class="rating result" title="100%">
+//          <div class="rating-result" title="100%">
 //              <span style="width:100%"><span>100%</span></span>
 //          </div>
 //      </div>
-//      <div class="rating summary item">
+//      <div class="rating-summary item">
 //          <span class="label"><span>rating +</span></span>
-//          <div class="rating result" title="20%">
+//          <div class="rating-result" title="20%">
 //              <span style="width:20%"><span>20%</span></span>
 //          </div>
 //      </div>
-//      <div class="rating summary item">
+//      <div class="rating-summary item">
 //          <span class="label"><span>Price</span></span>
-//          <div class="rating result" title="40%">
+//          <div class="rating-result" title="40%">
 //              <span style="width:40%"><span>40%</span></span>
 //          </div>
 //      </div>
@@ -422,25 +422,25 @@
 //  ```
 
 .example-rating-summary-6 {
-    .rating.summary {
-        .rating-summary();
+    .rating-summary {
+        .mixin-rating-summary();
     }
 }
 
 //  # Rating hide label mixin
 //
-//  The <code>.rating-summary-label-hide()</code> mixin is used to hide rating label in summary rating.
+//  The <code>.mixin-rating-summary-label-hide()</code> mixin is used to hide rating label in summary rating.
 //
 //  ``` html
 //  <div class="example-rating-summary-7">
 //      <span class="label"><span>Rating</span></span>
-//      <div class="rating result" title="40%">
+//      <div class="rating-result" title="40%">
 //          <span style="width:40%"><span>40</span></span>
 //      </div>
 //  </div>
 //  ```
 
 .example-rating-summary-7 {
-    .rating-summary();
-    .rating-summary-label-hide();
+    .mixin-rating-summary();
+    .mixin-rating-summary-label-hide();
 }
diff --git a/lib/web/css/docs/source/variables.less b/lib/web/css/docs/source/variables.less
index 3b353807a9d2341b16e875a6fddd30d2717d5bb1..9bb7bf08304def493d7fac3518ec787a7016562a 100644
--- a/lib/web/css/docs/source/variables.less
+++ b/lib/web/css/docs/source/variables.less
@@ -4975,7 +4975,7 @@
 //  </pre>
 //
 //  ## Rating variables
-//  #### The  <code>.rating-vote()</code> and <code>.rating-summary()</code> mixin variables
+//  #### The  <code>.mixin-rating-vote()</code> and <code>.mixin-rating-summary()</code> mixin variables
 //
 //  <pre>
 //    <table>
diff --git a/lib/web/css/source/lib/rating.less b/lib/web/css/source/lib/rating.less
index cf088fea4a2388a3254aaebd74877e8727a608c3..896bc218770f6c19b4dc901c31ed7cf2f2838747 100644
--- a/lib/web/css/source/lib/rating.less
+++ b/lib/web/css/source/lib/rating.less
@@ -23,7 +23,7 @@
 //  */
 
 // rating-vote mixin
-.rating-vote(
+.mixin-rating-vote(
     @_icon-count: @rating-icon-count,
     @_icon-content: @rating-icon-content,
     @_icon-font: @rating-icon-font,
@@ -40,7 +40,7 @@
             @_icon-letter-spacing,
             @_icon-color
         );
-        ._rating-icons-content(
+        .mixin-rating-icons-content(
             @_icon-count,
             @_icon-content
         );
@@ -93,7 +93,7 @@
 }
 
 // rating-summary mixin
-.rating-summary(
+.mixin-rating-summary(
     @_icon-count: @rating-icon-count,
     @_icon-content: @rating-icon-content,
     @_icon-font: @rating-icon-font,
@@ -105,8 +105,8 @@
 ) {
     overflow: hidden;
     ._rating-label-hide(@_label-hide);
-    .rating.result {
-        width: (@_icon-font-size * @_icon-count) - (abs(@_icon-letter-spacing) * (@_icon-count - 1));
+    .rating-result {
+        width: (@_icon-font-size * @_icon-count) + ceil(@_icon-letter-spacing * (@_icon-count - 1));
         &:before {
             position: absolute;
             z-index: 1;
@@ -150,7 +150,7 @@
     }
 }
 
-.rating-summary-label-hide() {
+.mixin-rating-summary-label-hide() {
     .label {
         .visually-hidden();
     }
@@ -158,7 +158,7 @@
 
 // Internal use mixins
 ._rating-label-hide(@_label-hide) when (@_label-hide = true) {
-    .rating-summary-label-hide();
+    .mixin-rating-summary-label-hide();
 }
 
 ._rating-iteration(
@@ -169,7 +169,7 @@
         .rating-@{_index} {
             z-index: @_icon-count - (@_index - 2);
             &:before {
-               ._rating-icons-content(@_index, @_icon-content);
+               .mixin-rating-icons-content(@_index, @_icon-content);
             }
         }
         // next iteration
@@ -195,6 +195,7 @@
     font-weight: normal;
     -webkit-font-smoothing: antialiased;
     color: @_icon-color;
+    vertical-align: top;
 }
 
 ._rating-summary-icon-default(
@@ -207,7 +208,7 @@
 ) {
     display: block;
     font-family: @_icon-font;
-    ._rating-icons-content(@_icon-count, @_icon-content);
+    .mixin-rating-icons-content(@_icon-count, @_icon-content);
     font-style: normal;
     font-size: @_icon-font-size;
     line-height: @_icon-font-size;
@@ -219,70 +220,70 @@
     color: @_icon-color;
 }
 
-._rating-icons-content(
+.mixin-rating-icons-content(
     @_icon-count: @rating-icon-count,
     @_icon-content: @rating-icon-content
 ) when (@_icon-count = 10) {
     content: @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content;
 }
 
-._rating-icons-content(
+.mixin-rating-icons-content(
     @_icon-count: @rating-icon-count,
     @_icon-content: @rating-icon-content
 ) when (@_icon-count = 9) {
     content: @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content;
 }
 
-._rating-icons-content(
+.mixin-rating-icons-content(
     @_icon-count: @rating-icon-count,
     @_icon-content: @rating-icon-content
 ) when (@_icon-count = 8) {
     content: @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content;
 }
 
-._rating-icons-content(
+.mixin-rating-icons-content(
     @_icon-count: @rating-icon-count,
     @_icon-content: @rating-icon-content
 ) when (@_icon-count = 7) {
     content: @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content;
 }
 
-._rating-icons-content(
+.mixin-rating-icons-content(
     @_icon-count: @rating-icon-count,
     @_icon-content: @rating-icon-content
 ) when (@_icon-count = 6) {
     content: @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content;
 }
 
-._rating-icons-content(
+.mixin-rating-icons-content(
     @_icon-count: @rating-icon-count,
     @_icon-content: @rating-icon-content
 ) when (@_icon-count = 5) {
     content: @_icon-content @_icon-content @_icon-content @_icon-content @_icon-content;
 }
 
-._rating-icons-content(
+.mixin-rating-icons-content(
     @_icon-count: @rating-icon-count,
     @_icon-content: @rating-icon-content
 ) when (@_icon-count = 4) {
     content: @_icon-content @_icon-content @_icon-content @_icon-content;
 }
 
-._rating-icons-content(
+.mixin-rating-icons-content(
     @_icon-count: @rating-icon-count,
     @_icon-content: @rating-icon-content
 ) when (@_icon-count = 3) {
     content: @_icon-content @_icon-content @_icon-content;
 }
 
-._rating-icons-content(
+.mixin-rating-icons-content(
     @_icon-count: @rating-icon-count,
     @_icon-content: @rating-icon-content
 ) when (@_icon-count = 2) {
     content: @_icon-content @_icon-content;
 }
 
-._rating-icons-content(
+.mixin-rating-icons-content(
     @_icon-count: @rating-icon-count,
     @_icon-content: @rating-icon-content
 ) when (@_icon-count = 1) {
diff --git a/lib/web/css/source/lib/responsive.less b/lib/web/css/source/lib/responsive.less
index 7282ffdf5981dd50df663b2f32af76a6561ef5dd..ac1a4d76ec00628263ca32aa2f809ce4919fcebb 100644
--- a/lib/web/css/source/lib/responsive.less
+++ b/lib/web/css/source/lib/responsive.less
@@ -23,12 +23,16 @@
 //  */
 
 // Small screens only
-.responsive-smaller(@break-point-0) {};
+.responsive-smaller(@break-point-0) {}
 
 @media all and (max-width: @break-point-0) {
     .responsive-smaller(@break-point-0);
 }
 
+@media all and (max-width: @break-point-1) {
+    .responsive-smaller(@break-point-1);
+}
+
 @media all and (min-width: @break-point-0) {
     .responsive(@break-point-0);
 }
diff --git a/lib/web/css/source/lib/tables.less b/lib/web/css/source/lib/tables.less
index a1e228d46f2d548dfbeb4c222061886359bc9109..cfa03de00b2f9482a6a687c5fc2fc291cca61c5a 100644
--- a/lib/web/css/source/lib/tables.less
+++ b/lib/web/css/source/lib/tables.less
@@ -30,7 +30,7 @@
 ) {
     border-collapse: collapse;
     border-spacing: 0;
-    .css(margin-bottom, @table-margin-bottom);
+    .css(margin-bottom, @_table-margin-bottom);
     max-width: 100%;
     .css(width, @_table-width);
     th {
@@ -57,7 +57,7 @@
         > tr {
             > th,
             > td {
-                padding: @_cell-padding-vertical @_cell-padding-horizontal;
+                .css(padding, @_cell-padding-vertical @_cell-padding-horizontal);
             }
         }
     }
@@ -112,18 +112,18 @@
     @_table-td-bg: @table-td-bg,
     @_table-body-th-bg: @table-body-th-bg
 ) {
-    .add-background(@_table-bg);
+    .css(background, @_table-bg);
     > thead {
-        .add-background(@_table-head-bg);
+        .css(background, @_table-head-bg);
     }
     > tfoot {
-        .add-background(@_table-foot-bg);
+        .css(background, @_table-foot-bg);
     }
     > tbody > tr > td {
-        .add-background(@_table-td-bg);
+        .css(background, @_table-td-bg);
     }
     > tbody > tr >th {
-        .add-background(@_table-body-th-bg);
+        .css(background, @_table-body-th-bg);
     }
 }
 
@@ -142,10 +142,10 @@
     > tfoot {
         > tr {
             > td {
-                padding: @_td-padding-top @_td-padding-right @_td-padding-bottom @_td-padding-left;
+                .css(padding, @_td-padding-top @_td-padding-right @_td-padding-bottom @_td-padding-left);
             }
             > th {
-                padding: @_th-padding-top @_th-padding-right @_th-padding-bottom @_th-padding-left;
+                .css(padding, @_th-padding-top @_th-padding-right @_th-padding-bottom @_th-padding-left);
             }
         }
     }
@@ -157,14 +157,14 @@
     @_border-style: @table-border-style,
     @_border-color: @table-border-color
 ) when (@_type = normal){
-    border: @_border-width @_border-style @_border-color;
+    .css(border, @_border-width @_border-style @_border-color);
     > thead,
     > tbody,
     > tfoot {
         > tr {
             > th,
             > td {
-                border: @_border-width @_border-style @_border-color;
+                .css(border, @_border-width @_border-style @_border-color);
             }
         }
     }
@@ -182,7 +182,7 @@
         > tr {
             > th,
             > td {
-                border-top: @table-border-width @table-border-style @table-border-color;
+                .css(border-top, @_border-width @_border-style @_border-color);
             }
         }
     }
@@ -197,7 +197,7 @@
         }
     }
     > tbody + tbody {
-        border-top: @table-border-width @table-border-style darken(@table-border-color, 25% );
+        .css(border-top, @_border-width @_border-style @_border-color);
     }
 }
 
@@ -213,7 +213,7 @@
         > tr {
             > th,
             > td {
-                border-left: @table-border-width @table-border-style @table-border-color;
+                .css(border-left, @_border-width @_border-style @_border-color);
                 &:first-child {
                     border-left: none;
                 }
@@ -243,7 +243,7 @@
         > tr {
             > th,
             > td {
-                border-bottom: @_border-width @_border-style @_border-color;
+                .css(border-bottom, @_border-width @_border-style @_border-color);
             }
         }
     }
@@ -277,8 +277,8 @@
     > tbody > tr:nth-child(odd) {
         > td,
         > th {
-            .add-background(@_stripped-bg);
-            color: @_stripped-color;
+            .css(background, @_stripped-bg);
+            .css(color, @_stripped-color);
         }
     }
 }
@@ -292,8 +292,8 @@
     > tbody > tr:nth-child(even) {
         > td,
         > th {
-            .add-background(@_stripped-bg);
-            color: @_stripped-color;
+            .css(background, @_stripped-bg);
+            .css(color, @_stripped-color);
         }
     }
 }
@@ -310,8 +310,8 @@
         > tr {
             > th:nth-child(odd),
             > td:nth-child(odd) {
-                .add-background(@_stripped-bg);
-                color: @_stripped-color;
+                .css(background, @_stripped-bg);
+                .css(color, @_stripped-color);
             }
         }
     }
@@ -329,8 +329,8 @@
         > tr {
             > th:nth-child(even),
             > td:nth-child(even) {
-                .add-background(@_stripped-bg);
-                .add-color(@_stripped-color)
+                .css(background, @_stripped-bg);
+                .css(color, @_stripped-color);
             }
         }
     }
@@ -343,13 +343,13 @@
     > tbody > tr:nth-child(even):hover {
         > td,
         > th {
-            .add-background(@_cell-bg-hover);
+            .css(background, @_cell-bg-hover);
         }
     }
     > tbody > tr:nth-child(odd):hover {
         > td,
         > th {
-            .add-background(@_cell-odd-bg-hover)
+            .css(background, @_cell-odd-bg-hover);
         }
     }
 }
@@ -368,7 +368,7 @@
             > tr {
                 > th,
                 > td {
-                    white-space: nowrap;
+                    //white-space: nowrap;
                 }
             }
         }
@@ -383,7 +383,7 @@
 ) when (@_reset-table-striped = false) and (@_reset-table-hover = false){
     ._responsive-table(@_table-bg-responsive: @_table-bg-responsive);
     > tbody > tr > th {
-        background-color: @_table-th-bg-responsive;
+        .css(background-color, @_table-th-bg-responsive);
     }
 }
 
@@ -412,7 +412,7 @@
 ) when (@_reset-table-striped = true) and (@_reset-table-hover = false){
     .table-striped(@_stripped-bg: @_table-bg-responsive);
     ._responsive-table(@_table-bg-responsive: @_table-bg-responsive);
-    background-color: @_table-th-bg-responsive;
+    .css(background-color, @_table-th-bg-responsive);
 }
 
 .table-responsive(
@@ -452,9 +452,9 @@
             @_table-caption-line-height,
             @_table-caption-font-style
         );
-        text-align: @_table-caption-alignment;
-        margin-top: @_table-caption-margin-top;
-        margin-bottom: @_table-caption-margin-bottom;
+        .css(text-align, @_table-caption-alignment);
+        .css(margin-top, @_table-caption-margin-top);
+        .css(margin-bottom, @_table-caption-margin-bottom);
     }
 }
 
@@ -477,7 +477,7 @@
 
 ._responsive-table(@_table-bg-responsive: @_table-bg-responsive) {
     border: none;
-    .add-background(@_table-bg-responsive);
+    .css(background, @_table-bg-responsive);
     > thead > tr > th {
         display: none;
     }
@@ -488,9 +488,9 @@
             padding: (@table-cell-padding-vertical / 2) @table-cell-padding-horizontal;
             border-bottom: none;
             &:before {
-                content: attr(data-th)": ";
+                content: attr(data-th)"";
                 display: inline-block;
-                padding-right: @table-cell-padding-horizontal;
+                .css(padding-right, @table-cell-padding-horizontal);
                 .typography (
                     @_font-size: @table-th-font-size,
                     @_color: @table-th-color,
@@ -503,7 +503,7 @@
         }
     }
     > tbody > tr > td {
-        .add-background(@_table-bg-responsive);
+        .css(background, @_table-bg-responsive);
     }
     > tfoot > tr > {
         td,
diff --git a/lib/web/css/source/lib/variables.less b/lib/web/css/source/lib/variables.less
index 52ae6ed1e44bd80f5cd8750997940c7b0b5b5dda..1242f524db35f91e4a985880623d1784e48c3882 100644
--- a/lib/web/css/source/lib/variables.less
+++ b/lib/web/css/source/lib/variables.less
@@ -233,7 +233,7 @@
 //--------------------------------------
 @table-width: 100%;
 @table-margin-bottom: false;
-@table-bg: transparent;
+@table-bg: false;
 @table-head-bg: @table-bg;
 @table-foot-bg: @table-bg;
 @table-td-bg: @table-bg;
@@ -249,34 +249,34 @@
 @table-caption-hide: false; //Default value false, set true to hide caption
 @table-caption-font-size: @font-size-l;
 @table-caption-color: @text-color-intense;
-@table-caption-font-family: @font-family-base;
-@table-caption-font-weight: @font-weight-base;
-@table-caption-font-style: @font-style-base;
-@table-caption-line-height: @line-height-base;
+@table-caption-font-family: false;
+@table-caption-font-weight: false;
+@table-caption-font-style: false;
+@table-caption-line-height: false;
 @table-caption-alignment: left;
 @table-caption-margin-top: @indent-base;
 @table-caption-margin-bottom: @indent-s-base;
 
-@table-td-font-size: @font-size-base;
-@table-td-color: @text-color;
-@table-td-font-family: @font-family-base;
-@table-td-font-weight: @font-weight-base;
-@table-td-line-height: @line-height-base;
-@table-td-font-style: @font-style-base;
+@table-td-font-size: false;
+@table-td-color: false;
+@table-td-font-family: false;
+@table-td-font-weight: false;
+@table-td-line-height: false;
+@table-td-font-style: false;
 
-@table-th-font-size: @font-size-base;
+@table-th-font-size: false;
 @table-th-color: @text-color-intense;
-@table-th-font-family: @font-family-base;
+@table-th-font-family: false;
 @table-th-font-weight: @font-weight-bold;
-@table-th-line-height: @line-height-base;
-@table-th-font-style: @font-style-base;
+@table-th-line-height: false;
+@table-th-font-style: false;
 
 @table-cell-bg-stripped: lighten(@table-cell-bg-hover, 15%);
 @table-cell-bg-hover: @panel-bg;
 @table-cell-color-stripped: @table-td-color;
 
 @table-bg-responsive: @table-bg;
-@table-th-bg-responsive: @table-cell-bg-stripped;
+@table-th-bg-responsive: false;
 
 //
 //    Page layout variables
diff --git a/lib/web/jquery/jquery.mobile.custom.js b/lib/web/jquery/jquery.mobile.custom.js
new file mode 100644
index 0000000000000000000000000000000000000000..f289b97b91d832621770f1cc56a54c04e1dd567d
--- /dev/null
+++ b/lib/web/jquery/jquery.mobile.custom.js
@@ -0,0 +1,864 @@
+/*
+* jQuery Mobile v1.4.3
+* http://jquerymobile.com
+*
+* Copyright 2010, 2014 jQuery Foundation, Inc. and other contributors
+* Released under the MIT license.
+* http://jquery.org/license
+*
+*/
+
+(function ( root, doc, factory ) {
+	if ( typeof define === "function" && define.amd ) {
+		// AMD. Register as an anonymous module.
+		define( [ "jquery" ], function ( $ ) {
+			factory( $, root, doc );
+			return $.mobile;
+		});
+	} else {
+		// Browser globals
+		factory( root.jQuery, root, doc );
+	}
+}( this, document, function ( jQuery, window, document, undefined ) {// This plugin is an experiment for abstracting away the touch and mouse
+// events so that developers don't have to worry about which method of input
+// the device their document is loaded on supports.
+//
+// The idea here is to allow the developer to register listeners for the
+// basic mouse events, such as mousedown, mousemove, mouseup, and click,
+// and the plugin will take care of registering the correct listeners
+// behind the scenes to invoke the listener at the fastest possible time
+// for that device, while still retaining the order of event firing in
+// the traditional mouse environment, should multiple handlers be registered
+// on the same element for different events.
+//
+// The current version exposes the following virtual events to jQuery bind methods:
+// "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel"
+
+(function( $, window, document, undefined ) {
+
+var dataPropertyName = "virtualMouseBindings",
+	touchTargetPropertyName = "virtualTouchID",
+	virtualEventNames = "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split( " " ),
+	touchEventProps = "clientX clientY pageX pageY screenX screenY".split( " " ),
+	mouseHookProps = $.event.mouseHooks ? $.event.mouseHooks.props : [],
+	mouseEventProps = $.event.props.concat( mouseHookProps ),
+	activeDocHandlers = {},
+	resetTimerID = 0,
+	startX = 0,
+	startY = 0,
+	didScroll = false,
+	clickBlockList = [],
+	blockMouseTriggers = false,
+	blockTouchTriggers = false,
+	eventCaptureSupported = "addEventListener" in document,
+	$document = $( document ),
+	nextTouchID = 1,
+	lastTouchID = 0, threshold,
+	i;
+
+$.vmouse = {
+	moveDistanceThreshold: 10,
+	clickDistanceThreshold: 10,
+	resetTimerDuration: 1500
+};
+
+function getNativeEvent( event ) {
+
+	while ( event && typeof event.originalEvent !== "undefined" ) {
+		event = event.originalEvent;
+	}
+	return event;
+}
+
+function createVirtualEvent( event, eventType ) {
+
+	var t = event.type,
+		oe, props, ne, prop, ct, touch, i, j, len;
+
+	event = $.Event( event );
+	event.type = eventType;
+
+	oe = event.originalEvent;
+	props = $.event.props;
+
+	// addresses separation of $.event.props in to $.event.mouseHook.props and Issue 3280
+	// https://github.com/jquery/jquery-mobile/issues/3280
+	if ( t.search( /^(mouse|click)/ ) > -1 ) {
+		props = mouseEventProps;
+	}
+
+	// copy original event properties over to the new event
+	// this would happen if we could call $.event.fix instead of $.Event
+	// but we don't have a way to force an event to be fixed multiple times
+	if ( oe ) {
+		for ( i = props.length, prop; i; ) {
+			prop = props[ --i ];
+			event[ prop ] = oe[ prop ];
+		}
+	}
+
+	// make sure that if the mouse and click virtual events are generated
+	// without a .which one is defined
+	if ( t.search(/mouse(down|up)|click/) > -1 && !event.which ) {
+		event.which = 1;
+	}
+
+	if ( t.search(/^touch/) !== -1 ) {
+		ne = getNativeEvent( oe );
+		t = ne.touches;
+		ct = ne.changedTouches;
+		touch = ( t && t.length ) ? t[0] : ( ( ct && ct.length ) ? ct[ 0 ] : undefined );
+
+		if ( touch ) {
+			for ( j = 0, len = touchEventProps.length; j < len; j++) {
+				prop = touchEventProps[ j ];
+				event[ prop ] = touch[ prop ];
+			}
+		}
+	}
+
+	return event;
+}
+
+function getVirtualBindingFlags( element ) {
+
+	var flags = {},
+		b, k;
+
+	while ( element ) {
+
+		b = $.data( element, dataPropertyName );
+
+		for (  k in b ) {
+			if ( b[ k ] ) {
+				flags[ k ] = flags.hasVirtualBinding = true;
+			}
+		}
+		element = element.parentNode;
+	}
+	return flags;
+}
+
+function getClosestElementWithVirtualBinding( element, eventType ) {
+	var b;
+	while ( element ) {
+
+		b = $.data( element, dataPropertyName );
+
+		if ( b && ( !eventType || b[ eventType ] ) ) {
+			return element;
+		}
+		element = element.parentNode;
+	}
+	return null;
+}
+
+function enableTouchBindings() {
+	blockTouchTriggers = false;
+}
+
+function disableTouchBindings() {
+	blockTouchTriggers = true;
+}
+
+function enableMouseBindings() {
+	lastTouchID = 0;
+	clickBlockList.length = 0;
+	blockMouseTriggers = false;
+
+	// When mouse bindings are enabled, our
+	// touch bindings are disabled.
+	disableTouchBindings();
+}
+
+function disableMouseBindings() {
+	// When mouse bindings are disabled, our
+	// touch bindings are enabled.
+	enableTouchBindings();
+}
+
+function startResetTimer() {
+	clearResetTimer();
+	resetTimerID = setTimeout( function() {
+		resetTimerID = 0;
+		enableMouseBindings();
+	}, $.vmouse.resetTimerDuration );
+}
+
+function clearResetTimer() {
+	if ( resetTimerID ) {
+		clearTimeout( resetTimerID );
+		resetTimerID = 0;
+	}
+}
+
+function triggerVirtualEvent( eventType, event, flags ) {
+	var ve;
+
+	if ( ( flags && flags[ eventType ] ) ||
+				( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) {
+
+		ve = createVirtualEvent( event, eventType );
+
+		$( event.target).trigger( ve );
+	}
+
+	return ve;
+}
+
+function mouseEventCallback( event ) {
+	var touchID = $.data( event.target, touchTargetPropertyName ),
+		ve;
+
+	if ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ) {
+		ve = triggerVirtualEvent( "v" + event.type, event );
+		if ( ve ) {
+			if ( ve.isDefaultPrevented() ) {
+				event.preventDefault();
+			}
+			if ( ve.isPropagationStopped() ) {
+				event.stopPropagation();
+			}
+			if ( ve.isImmediatePropagationStopped() ) {
+				event.stopImmediatePropagation();
+			}
+		}
+	}
+}
+
+function handleTouchStart( event ) {
+
+	var touches = getNativeEvent( event ).touches,
+		target, flags, t;
+
+	if ( touches && touches.length === 1 ) {
+
+		target = event.target;
+		flags = getVirtualBindingFlags( target );
+
+		if ( flags.hasVirtualBinding ) {
+
+			lastTouchID = nextTouchID++;
+			$.data( target, touchTargetPropertyName, lastTouchID );
+
+			clearResetTimer();
+
+			disableMouseBindings();
+			didScroll = false;
+
+			t = getNativeEvent( event ).touches[ 0 ];
+			startX = t.pageX;
+			startY = t.pageY;
+
+			triggerVirtualEvent( "vmouseover", event, flags );
+			triggerVirtualEvent( "vmousedown", event, flags );
+		}
+	}
+}
+
+function handleScroll( event ) {
+	if ( blockTouchTriggers ) {
+		return;
+	}
+
+	if ( !didScroll ) {
+		triggerVirtualEvent( "vmousecancel", event, getVirtualBindingFlags( event.target ) );
+	}
+
+	didScroll = true;
+	startResetTimer();
+}
+
+function handleTouchMove( event ) {
+	if ( blockTouchTriggers ) {
+		return;
+	}
+
+	var t = getNativeEvent( event ).touches[ 0 ],
+		didCancel = didScroll,
+		moveThreshold = $.vmouse.moveDistanceThreshold,
+		flags = getVirtualBindingFlags( event.target );
+
+		didScroll = didScroll ||
+			( Math.abs( t.pageX - startX ) > moveThreshold ||
+				Math.abs( t.pageY - startY ) > moveThreshold );
+
+	if ( didScroll && !didCancel ) {
+		triggerVirtualEvent( "vmousecancel", event, flags );
+	}
+
+	triggerVirtualEvent( "vmousemove", event, flags );
+	startResetTimer();
+}
+
+function handleTouchEnd( event ) {
+	if ( blockTouchTriggers ) {
+		return;
+	}
+
+	disableTouchBindings();
+
+	var flags = getVirtualBindingFlags( event.target ),
+		ve, t;
+	triggerVirtualEvent( "vmouseup", event, flags );
+
+	if ( !didScroll ) {
+		ve = triggerVirtualEvent( "vclick", event, flags );
+		if ( ve && ve.isDefaultPrevented() ) {
+			// The target of the mouse events that follow the touchend
+			// event don't necessarily match the target used during the
+			// touch. This means we need to rely on coordinates for blocking
+			// any click that is generated.
+			t = getNativeEvent( event ).changedTouches[ 0 ];
+			clickBlockList.push({
+				touchID: lastTouchID,
+				x: t.clientX,
+				y: t.clientY
+			});
+
+			// Prevent any mouse events that follow from triggering
+			// virtual event notifications.
+			blockMouseTriggers = true;
+		}
+	}
+	triggerVirtualEvent( "vmouseout", event, flags);
+	didScroll = false;
+
+	startResetTimer();
+}
+
+function hasVirtualBindings( ele ) {
+	var bindings = $.data( ele, dataPropertyName ),
+		k;
+
+	if ( bindings ) {
+		for ( k in bindings ) {
+			if ( bindings[ k ] ) {
+				return true;
+			}
+		}
+	}
+	return false;
+}
+
+function dummyMouseHandler() {}
+
+function getSpecialEventObject( eventType ) {
+	var realType = eventType.substr( 1 );
+
+	return {
+		setup: function(/* data, namespace */) {
+			// If this is the first virtual mouse binding for this element,
+			// add a bindings object to its data.
+
+			if ( !hasVirtualBindings( this ) ) {
+				$.data( this, dataPropertyName, {} );
+			}
+
+			// If setup is called, we know it is the first binding for this
+			// eventType, so initialize the count for the eventType to zero.
+			var bindings = $.data( this, dataPropertyName );
+			bindings[ eventType ] = true;
+
+			// If this is the first virtual mouse event for this type,
+			// register a global handler on the document.
+
+			activeDocHandlers[ eventType ] = ( activeDocHandlers[ eventType ] || 0 ) + 1;
+
+			if ( activeDocHandlers[ eventType ] === 1 ) {
+				$document.bind( realType, mouseEventCallback );
+			}
+
+			// Some browsers, like Opera Mini, won't dispatch mouse/click events
+			// for elements unless they actually have handlers registered on them.
+			// To get around this, we register dummy handlers on the elements.
+
+			$( this ).bind( realType, dummyMouseHandler );
+
+			// For now, if event capture is not supported, we rely on mouse handlers.
+			if ( eventCaptureSupported ) {
+				// If this is the first virtual mouse binding for the document,
+				// register our touchstart handler on the document.
+
+				activeDocHandlers[ "touchstart" ] = ( activeDocHandlers[ "touchstart" ] || 0) + 1;
+
+				if ( activeDocHandlers[ "touchstart" ] === 1 ) {
+					$document.bind( "touchstart", handleTouchStart )
+						.bind( "touchend", handleTouchEnd )
+
+						// On touch platforms, touching the screen and then dragging your finger
+						// causes the window content to scroll after some distance threshold is
+						// exceeded. On these platforms, a scroll prevents a click event from being
+						// dispatched, and on some platforms, even the touchend is suppressed. To
+						// mimic the suppression of the click event, we need to watch for a scroll
+						// event. Unfortunately, some platforms like iOS don't dispatch scroll
+						// events until *AFTER* the user lifts their finger (touchend). This means
+						// we need to watch both scroll and touchmove events to figure out whether
+						// or not a scroll happenens before the touchend event is fired.
+
+						.bind( "touchmove", handleTouchMove )
+						.bind( "scroll", handleScroll );
+				}
+			}
+		},
+
+		teardown: function(/* data, namespace */) {
+			// If this is the last virtual binding for this eventType,
+			// remove its global handler from the document.
+
+			--activeDocHandlers[ eventType ];
+
+			if ( !activeDocHandlers[ eventType ] ) {
+				$document.unbind( realType, mouseEventCallback );
+			}
+
+			if ( eventCaptureSupported ) {
+				// If this is the last virtual mouse binding in existence,
+				// remove our document touchstart listener.
+
+				--activeDocHandlers[ "touchstart" ];
+
+				if ( !activeDocHandlers[ "touchstart" ] ) {
+					$document.unbind( "touchstart", handleTouchStart )
+						.unbind( "touchmove", handleTouchMove )
+						.unbind( "touchend", handleTouchEnd )
+						.unbind( "scroll", handleScroll );
+				}
+			}
+
+			var $this = $( this ),
+				bindings = $.data( this, dataPropertyName );
+
+			// teardown may be called when an element was
+			// removed from the DOM. If this is the case,
+			// jQuery core may have already stripped the element
+			// of any data bindings so we need to check it before
+			// using it.
+			if ( bindings ) {
+				bindings[ eventType ] = false;
+			}
+
+			// Unregister the dummy event handler.
+
+			$this.unbind( realType, dummyMouseHandler );
+
+			// If this is the last virtual mouse binding on the
+			// element, remove the binding data from the element.
+
+			if ( !hasVirtualBindings( this ) ) {
+				$this.removeData( dataPropertyName );
+			}
+		}
+	};
+}
+
+// Expose our custom events to the jQuery bind/unbind mechanism.
+
+for ( i = 0; i < virtualEventNames.length; i++ ) {
+	$.event.special[ virtualEventNames[ i ] ] = getSpecialEventObject( virtualEventNames[ i ] );
+}
+
+// Add a capture click handler to block clicks.
+// Note that we require event capture support for this so if the device
+// doesn't support it, we punt for now and rely solely on mouse events.
+if ( eventCaptureSupported ) {
+	document.addEventListener( "click", function( e ) {
+		var cnt = clickBlockList.length,
+			target = e.target,
+			x, y, ele, i, o, touchID;
+
+		if ( cnt ) {
+			x = e.clientX;
+			y = e.clientY;
+			threshold = $.vmouse.clickDistanceThreshold;
+
+			// The idea here is to run through the clickBlockList to see if
+			// the current click event is in the proximity of one of our
+			// vclick events that had preventDefault() called on it. If we find
+			// one, then we block the click.
+			//
+			// Why do we have to rely on proximity?
+			//
+			// Because the target of the touch event that triggered the vclick
+			// can be different from the target of the click event synthesized
+			// by the browser. The target of a mouse/click event that is synthesized
+			// from a touch event seems to be implementation specific. For example,
+			// some browsers will fire mouse/click events for a link that is near
+			// a touch event, even though the target of the touchstart/touchend event
+			// says the user touched outside the link. Also, it seems that with most
+			// browsers, the target of the mouse/click event is not calculated until the
+			// time it is dispatched, so if you replace an element that you touched
+			// with another element, the target of the mouse/click will be the new
+			// element underneath that point.
+			//
+			// Aside from proximity, we also check to see if the target and any
+			// of its ancestors were the ones that blocked a click. This is necessary
+			// because of the strange mouse/click target calculation done in the
+			// Android 2.1 browser, where if you click on an element, and there is a
+			// mouse/click handler on one of its ancestors, the target will be the
+			// innermost child of the touched element, even if that child is no where
+			// near the point of touch.
+
+			ele = target;
+
+			while ( ele ) {
+				for ( i = 0; i < cnt; i++ ) {
+					o = clickBlockList[ i ];
+					touchID = 0;
+
+					if ( ( ele === target && Math.abs( o.x - x ) < threshold && Math.abs( o.y - y ) < threshold ) ||
+								$.data( ele, touchTargetPropertyName ) === o.touchID ) {
+						// XXX: We may want to consider removing matches from the block list
+						//      instead of waiting for the reset timer to fire.
+						e.preventDefault();
+						e.stopPropagation();
+						return;
+					}
+				}
+				ele = ele.parentNode;
+			}
+		}
+	}, true);
+}
+})( jQuery, window, document );
+
+(function( $ ) {
+	$.mobile = {};
+}( jQuery ));
+
+	(function( $, undefined ) {
+		var support = {
+			touch: "ontouchend" in document
+		};
+
+		$.mobile.support = $.mobile.support || {};
+		$.extend( $.support, support );
+		$.extend( $.mobile.support, support );
+	}( jQuery ));
+
+
+(function( $, window, undefined ) {
+	var $document = $( document ),
+		supportTouch = $.mobile.support.touch,
+		scrollEvent = "touchmove scroll",
+		touchStartEvent = supportTouch ? "touchstart" : "mousedown",
+		touchStopEvent = supportTouch ? "touchend" : "mouseup",
+		touchMoveEvent = supportTouch ? "touchmove" : "mousemove";
+
+	// setup new event shortcuts
+	$.each( ( "touchstart touchmove touchend " +
+		"tap taphold " +
+		"swipe swipeleft swiperight " +
+		"scrollstart scrollstop" ).split( " " ), function( i, name ) {
+
+		$.fn[ name ] = function( fn ) {
+			return fn ? this.bind( name, fn ) : this.trigger( name );
+		};
+
+		// jQuery < 1.8
+		if ( $.attrFn ) {
+			$.attrFn[ name ] = true;
+		}
+	});
+
+	function triggerCustomEvent( obj, eventType, event, bubble ) {
+		var originalType = event.type;
+		event.type = eventType;
+		if ( bubble ) {
+			$.event.trigger( event, undefined, obj );
+		} else {
+			$.event.dispatch.call( obj, event );
+		}
+		event.type = originalType;
+	}
+
+	// also handles scrollstop
+	$.event.special.scrollstart = {
+
+		enabled: true,
+		setup: function() {
+
+			var thisObject = this,
+				$this = $( thisObject ),
+				scrolling,
+				timer;
+
+			function trigger( event, state ) {
+				scrolling = state;
+				triggerCustomEvent( thisObject, scrolling ? "scrollstart" : "scrollstop", event );
+			}
+
+			// iPhone triggers scroll after a small delay; use touchmove instead
+			$this.bind( scrollEvent, function( event ) {
+
+				if ( !$.event.special.scrollstart.enabled ) {
+					return;
+				}
+
+				if ( !scrolling ) {
+					trigger( event, true );
+				}
+
+				clearTimeout( timer );
+				timer = setTimeout( function() {
+					trigger( event, false );
+				}, 50 );
+			});
+		},
+		teardown: function() {
+			$( this ).unbind( scrollEvent );
+		}
+	};
+
+	// also handles taphold
+	$.event.special.tap = {
+		tapholdThreshold: 750,
+		emitTapOnTaphold: true,
+		setup: function() {
+			var thisObject = this,
+				$this = $( thisObject ),
+				isTaphold = false;
+
+			$this.bind( "vmousedown", function( event ) {
+				isTaphold = false;
+				if ( event.which && event.which !== 1 ) {
+					return false;
+				}
+
+				var origTarget = event.target,
+					timer;
+
+				function clearTapTimer() {
+					clearTimeout( timer );
+				}
+
+				function clearTapHandlers() {
+					clearTapTimer();
+
+					$this.unbind( "vclick", clickHandler )
+						.unbind( "vmouseup", clearTapTimer );
+					$document.unbind( "vmousecancel", clearTapHandlers );
+				}
+
+				function clickHandler( event ) {
+					clearTapHandlers();
+
+					// ONLY trigger a 'tap' event if the start target is
+					// the same as the stop target.
+					if ( !isTaphold && origTarget === event.target ) {
+						triggerCustomEvent( thisObject, "tap", event );
+					} else if ( isTaphold ) {
+						event.preventDefault();
+					}
+				}
+
+				$this.bind( "vmouseup", clearTapTimer )
+					.bind( "vclick", clickHandler );
+				$document.bind( "vmousecancel", clearTapHandlers );
+
+				timer = setTimeout( function() {
+					if ( !$.event.special.tap.emitTapOnTaphold ) {
+						isTaphold = true;
+					}
+					triggerCustomEvent( thisObject, "taphold", $.Event( "taphold", { target: origTarget } ) );
+				}, $.event.special.tap.tapholdThreshold );
+			});
+		},
+		teardown: function() {
+			$( this ).unbind( "vmousedown" ).unbind( "vclick" ).unbind( "vmouseup" );
+			$document.unbind( "vmousecancel" );
+		}
+	};
+
+	// Also handles swipeleft, swiperight
+	$.event.special.swipe = {
+
+		// More than this horizontal displacement, and we will suppress scrolling.
+		scrollSupressionThreshold: 30,
+
+		// More time than this, and it isn't a swipe.
+		durationThreshold: 1000,
+
+		// Swipe horizontal displacement must be more than this.
+		horizontalDistanceThreshold: 30,
+
+		// Swipe vertical displacement must be less than this.
+		verticalDistanceThreshold: 30,
+
+		getLocation: function ( event ) {
+			var winPageX = window.pageXOffset,
+				winPageY = window.pageYOffset,
+				x = event.clientX,
+				y = event.clientY;
+
+			if ( event.pageY === 0 && Math.floor( y ) > Math.floor( event.pageY ) ||
+				event.pageX === 0 && Math.floor( x ) > Math.floor( event.pageX ) ) {
+
+				// iOS4 clientX/clientY have the value that should have been
+				// in pageX/pageY. While pageX/page/ have the value 0
+				x = x - winPageX;
+				y = y - winPageY;
+			} else if ( y < ( event.pageY - winPageY) || x < ( event.pageX - winPageX ) ) {
+
+				// Some Android browsers have totally bogus values for clientX/Y
+				// when scrolling/zooming a page. Detectable since clientX/clientY
+				// should never be smaller than pageX/pageY minus page scroll
+				x = event.pageX - winPageX;
+				y = event.pageY - winPageY;
+			}
+
+			return {
+				x: x,
+				y: y
+			};
+		},
+
+		start: function( event ) {
+			var data = event.originalEvent.touches ?
+					event.originalEvent.touches[ 0 ] : event,
+				location = $.event.special.swipe.getLocation( data );
+			return {
+						time: ( new Date() ).getTime(),
+						coords: [ location.x, location.y ],
+						origin: $( event.target )
+					};
+		},
+
+		stop: function( event ) {
+			var data = event.originalEvent.touches ?
+					event.originalEvent.touches[ 0 ] : event,
+				location = $.event.special.swipe.getLocation( data );
+			return {
+						time: ( new Date() ).getTime(),
+						coords: [ location.x, location.y ]
+					};
+		},
+
+		handleSwipe: function( start, stop, thisObject, origTarget ) {
+			if ( stop.time - start.time < $.event.special.swipe.durationThreshold &&
+				Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold &&
+				Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) {
+				var direction = start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight";
+
+				triggerCustomEvent( thisObject, "swipe", $.Event( "swipe", { target: origTarget, swipestart: start, swipestop: stop }), true );
+				triggerCustomEvent( thisObject, direction,$.Event( direction, { target: origTarget, swipestart: start, swipestop: stop } ), true );
+				return true;
+			}
+			return false;
+
+		},
+
+		// This serves as a flag to ensure that at most one swipe event event is
+		// in work at any given time
+		eventInProgress: false,
+
+		setup: function() {
+			var events,
+				thisObject = this,
+				$this = $( thisObject ),
+				context = {};
+
+			// Retrieve the events data for this element and add the swipe context
+			events = $.data( this, "mobile-events" );
+			if ( !events ) {
+				events = { length: 0 };
+				$.data( this, "mobile-events", events );
+			}
+			events.length++;
+			events.swipe = context;
+
+			context.start = function( event ) {
+
+				// Bail if we're already working on a swipe event
+				if ( $.event.special.swipe.eventInProgress ) {
+					return;
+				}
+				$.event.special.swipe.eventInProgress = true;
+
+				var stop,
+					start = $.event.special.swipe.start( event ),
+					origTarget = event.target,
+					emitted = false;
+
+				context.move = function( event ) {
+					if ( !start ) {
+						return;
+					}
+
+					stop = $.event.special.swipe.stop( event );
+					if ( !emitted ) {
+						emitted = $.event.special.swipe.handleSwipe( start, stop, thisObject, origTarget );
+						if ( emitted ) {
+
+							// Reset the context to make way for the next swipe event
+							$.event.special.swipe.eventInProgress = false;
+						}
+					}
+					// prevent scrolling
+					if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) {
+						event.preventDefault();
+					}
+				};
+
+				context.stop = function() {
+						emitted = true;
+
+						// Reset the context to make way for the next swipe event
+						$.event.special.swipe.eventInProgress = false;
+						$document.off( touchMoveEvent, context.move );
+						context.move = null;
+				};
+
+				$document.on( touchMoveEvent, context.move )
+					.one( touchStopEvent, context.stop );
+			};
+			$this.on( touchStartEvent, context.start );
+		},
+
+		teardown: function() {
+			var events, context;
+
+			events = $.data( this, "mobile-events" );
+			if ( events ) {
+				context = events.swipe;
+				delete events.swipe;
+				events.length--;
+				if ( events.length === 0 ) {
+					$.removeData( this, "mobile-events" );
+				}
+			}
+
+			if ( context ) {
+				if ( context.start ) {
+					$( this ).off( touchStartEvent, context.start );
+				}
+				if ( context.move ) {
+					$document.off( touchMoveEvent, context.move );
+				}
+				if ( context.stop ) {
+					$document.off( touchStopEvent, context.stop );
+				}
+			}
+		}
+	};
+	$.each({
+		scrollstop: "scrollstart",
+		taphold: "tap",
+		swipeleft: "swipe.left",
+		swiperight: "swipe.right"
+	}, function( event, sourceEvent ) {
+
+		$.event.special[ event ] = {
+			setup: function() {
+				$( this ).bind( sourceEvent, $.noop );
+			},
+			teardown: function() {
+				$( this ).unbind( sourceEvent );
+			}
+		};
+	});
+
+})( jQuery, this );
+
+
+}));
diff --git a/lib/web/mage/backend/form.js b/lib/web/mage/backend/form.js
index 11691e056b3949d01c01294917ba8d744604074a..38f638e272bc5a7636c42147a60d770623724581 100644
--- a/lib/web/mage/backend/form.js
+++ b/lib/web/mage/backend/form.js
@@ -109,7 +109,7 @@
         _storeAttribute: function(attrName) {
             this.oldAttributes = this.oldAttributes || {};
             if (!this.oldAttributes[attrName]) {
-                var prop = this.element.prop(attrName);
+                var prop = this.element.attr(attrName);
                 this.oldAttributes[attrName] = prop ? prop : '';
             }
         },
diff --git a/lib/web/mage/loader.js b/lib/web/mage/loader.js
index 07d9694c2b90a5ec4b17f27c6f3efbdbca665f34..9c7e78ee8e98f6f2a6fe530404adc99436403d29 100644
--- a/lib/web/mage/loader.js
+++ b/lib/web/mage/loader.js
@@ -27,7 +27,7 @@
         loaderStarted: 0,
         spinnerTemplate: $(undefined),
         options: {
-            icon: 'icon.gif',
+            icon: '',
             texts: {
                 loaderText: $.mage.__('Please wait...'),
                 imgAlt: $.mage.__('Loading...')
@@ -142,7 +142,8 @@
      */
     $.widget("mage.loaderAjax", {
         options: {
-            defaultContainer: '[data-container=body]'
+            defaultContainer: '[data-container=body]',
+            loadingClass: 'ajax-loading'
         },
         _create: function() {
             this._bind();
@@ -173,6 +174,8 @@
             return ctx;
         },
         _onAjaxSend: function(e, jqxhr, settings) {
+            $(this.options.defaultContainer).addClass(this.options.loadingClass);
+
             if (settings && settings.showLoader) {
                 var ctx = this._getJqueryObj(settings.loaderContext);
                 ctx.trigger('processStart');
@@ -186,6 +189,7 @@
             }
         },
         _onAjaxComplete: function(e, jqxhr, settings) {
+            $(this.options.defaultContainer).removeClass(this.options.loadingClass);
             if (settings && settings.showLoader) {
                 this._getJqueryObj(settings.loaderContext).trigger('processStop');
             }
diff --git a/lib/web/mage/menu.js b/lib/web/mage/menu.js
index f03f72041b5f594d28b2f9c6ffb92e1ae81ccd61..b43685a1eb0bbfdca519360424b7af1fb4e0902c 100644
--- a/lib/web/mage/menu.js
+++ b/lib/web/mage/menu.js
@@ -53,12 +53,29 @@
                 });
             }
 
-            $('.action.toggle.nav').on('click', function() {
-                $('.page-wrapper').toggleClass('open');
-                $('body').toggleClass('open');
-                $('html').toggleClass('open');
-            });
+            this._assignControls()._listen();
+        },
+
+        _assignControls: function() {
+            this.controls = {
+                toggleBtn: $('[data-action="toggle-nav"]'),
+                swipeArea: $('.panel.wrapper'),
+                wrapper: $('.page-wrapper')
+            };
+
+            return this;
+        },
+
+        _listen: function() {
+            var controls = this.controls;
+            var toggle = this.toggle;
+
+            this._on(controls.toggleBtn, { 'click'    : toggle });
+            this._on(controls.swipeArea, { 'swipeleft': toggle });
+        },
 
+        toggle: function() {
+            this.controls.wrapper.toggleClass('open');
         },
 
         //Add class for expanded option
diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js
index 9e7d5d8044f52164fe9123e2a48bf89ee566d30a..01d1f30e25b1ea149bbff8881685bcc6f7c299d3 100644
--- a/lib/web/mage/validation.js
+++ b/lib/web/mage/validation.js
@@ -545,7 +545,7 @@
             },
             'Please enter a valid social security number. For example 123-45-6789.'
         ],
-        "validate-zip": [
+        "validate-zip-us": [
             function(v) {
                 return $.mage.isEmptyNoTrim(v) || /(^\d{5}$)|(^\d{5}-\d{4}$)/.test(v);
 
@@ -611,11 +611,10 @@
         ],
         "validate-css-length": [
             function(v) {
-                if ($.mage.isEmptyNoTrim(v)) {
-                    return true;
+                if (v !== '') {
+                    return (/^[0-9]*\.*[0-9]+(px|pc|pt|ex|em|mm|cm|in|%)?$/).test(v);
                 }
-                v = $.mage.parseNumber(v);
-                return !isNaN(v) && v > 0;
+                return true;
             },
             'Please input a valid CSS-length. For example 100px or 77pt or 20em or .5ex or 50%.'
         ],
diff --git a/lib/web/prototype/validation.js b/lib/web/prototype/validation.js
index 798194949ad5a55b62ba77435c130f755363792d..ecee5cc3a24672025ac8f798e57a3db30ab35a59 100644
--- a/lib/web/prototype/validation.js
+++ b/lib/web/prototype/validation.js
@@ -621,7 +621,7 @@ Validation.addAllThese([
     ['validate-ssn', 'Please enter a valid social security number. For example 123-45-6789.', function(v) {
             return Validation.get('IsEmpty').test(v) || /^\d{3}-?\d{2}-?\d{4}$/.test(v);
             }],
-    ['validate-zip', 'Please enter a valid zip code. For example 90602 or 90602-1234.', function(v) {
+    ['validate-zip-us', 'Please enter a valid zip code. For example 90602 or 90602-1234.', function(v) {
             return Validation.get('IsEmpty').test(v) || /(^\d{5}$)|(^\d{5}-\d{4}$)/.test(v);
             }],
     ['validate-zip-international', 'Please enter a valid zip code.', function(v) {