You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ab...@apache.org on 2014/04/30 18:30:28 UTC

[1/2] git commit: AMBARI-5635 UI changes for required for MM support. (ababiichuk)

Repository: ambari
Updated Branches:
  refs/heads/trunk 27544b148 -> 68020574d


AMBARI-5635 UI changes for required for MM support. (ababiichuk)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/6cd8a802
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/6cd8a802
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/6cd8a802

Branch: refs/heads/trunk
Commit: 6cd8a8021e4138e0377c9903a9d0d3af182d0e6c
Parents: 27544b1
Author: aBabiichuk <ab...@cybervisiontech.com>
Authored: Wed Apr 30 17:54:02 2014 +0300
Committer: aBabiichuk <ab...@cybervisiontech.com>
Committed: Wed Apr 30 17:56:55 2014 +0300

----------------------------------------------------------------------
 ambari-web/app/controllers/main/host.js         |  6 ++-
 ambari-web/app/controllers/main/host/details.js | 40 +++++++++++-----
 ambari-web/app/controllers/main/service.js      |  6 ++-
 ambari-web/app/controllers/main/service/item.js |  2 +-
 ambari-web/app/utils/ajax/ajax.js               | 48 ++++++--------------
 .../app/utils/batch_scheduled_requests.js       | 41 +++++++++++++++--
 .../test/controllers/main/host/details_test.js  | 36 ++++++++++++++-
 7 files changed, 123 insertions(+), 56 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/6cd8a802/ambari-web/app/controllers/main/host.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host.js b/ambari-web/app/controllers/main/host.js
index 8b707d7..5f0c9af 100644
--- a/ambari-web/app/controllers/main/host.js
+++ b/ambari-web/app/controllers/main/host.js
@@ -194,6 +194,7 @@ App.MainHostController = Em.ArrayController.extend({
         query.push(subQuery.fmt(components.join(',')));
       }
     });
+    var hostNames = hosts.mapProperty('hostName').join(",");
     if (query.length) {
       query = query.join('|');
       App.ajax.send({
@@ -202,7 +203,8 @@ App.MainHostController = Em.ArrayController.extend({
         data: {
           query: query,
           state: operationData.action,
-          requestInfo: operationData.message
+          requestInfo: operationData.message,
+          hostName: hostNames
         },
         success: 'bulkOperationForHostComponentsSuccessCallback'
       });
@@ -226,7 +228,7 @@ App.MainHostController = Em.ArrayController.extend({
     hosts.forEach(function(host) {
       hostComponents.pushObjects(host.get('hostComponents').filterProperty('passiveState','OFF').toArray());
     });
-    batchUtils.restartHostComponents(hostComponents, Em.I18n.t('rollingrestart.context.allOnSelectedHosts'));
+    batchUtils.restartHostComponents(hostComponents, Em.I18n.t('rollingrestart.context.allOnSelectedHosts'), "HOST");
   },
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/6cd8a802/ambari-web/app/controllers/main/host/details.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host/details.js b/ambari-web/app/controllers/main/host/details.js
index 73fda3e..3113889 100644
--- a/ambari-web/app/controllers/main/host/details.js
+++ b/ambari-web/app/controllers/main/host/details.js
@@ -111,7 +111,7 @@ App.MainHostDetailsController = Em.Controller.extend({
    * @method sendStartComponentCommand
    */
   sendStartComponentCommand: function (component, context) {
-    var dataToSend = this.getDataToSend('STARTED', context);
+    var dataToSend = this.getDataToSend('STARTED', context, component);
     var data = {
       hostName: this.get('content.hostName'),
       component: component
@@ -127,14 +127,30 @@ App.MainHostDetailsController = Em.Controller.extend({
   },
   /**
    * construct meta data for query
-   * @param state
-   * @param context
-   * @return {Object}
-   */
-  getDataToSend: function (state, context) {
+   * @param {String} state
+   * @param {String} context
+   * @param {String|Array} component - componentName or Array of components
+   * @return {Object} request info
+   * @method getDataToSend creates request info to start/stop component(s)
+   */
+  getDataToSend: function (state, context, component) {
+    var operationLevel = {
+      "cluster_name":  App.get('clusterName'),
+      "host_name": this.get("content.hostName")
+    };
+
+    if (Array.isArray(component)) {
+      operationLevel["level"] = "HOST";
+    } else if(component){
+      operationLevel["level"] = "HOST_COMPONENT",
+      operationLevel["hostcomponent_name"] = component.get("componentName"),
+      operationLevel["service_name"] = component.get("service.serviceName")
+    }
+
     return {
       RequestInfo: {
-        "context": context
+        "context": context,
+        "operation_level": operationLevel
       },
       Body: {
         HostRoles: {
@@ -390,7 +406,7 @@ App.MainHostDetailsController = Em.Controller.extend({
    * @method sendStopComponentCommand
    */
   sendStopComponentCommand: function (component, context) {
-    var dataToSend = this.getDataToSend('INSTALLED', context);
+    var dataToSend = this.getDataToSend('INSTALLED', context, component);
     var data = {
       hostName: this.get('content.hostName'),
       component: component
@@ -431,7 +447,7 @@ App.MainHostDetailsController = Em.Controller.extend({
   restartComponent: function (event) {
     var component = event.context;
     return App.showConfirmationPopup(function () {
-      batchUtils.restartHostComponents([component], Em.I18n.t('rollingrestart.context.selectedComponentOnSelectedHost').format(component.get('displayName')));
+      batchUtils.restartHostComponents([component], Em.I18n.t('rollingrestart.context.selectedComponentOnSelectedHost').format(component.get('displayName')), "HOST_COMPONENT");
     });
   },
   /**
@@ -1356,7 +1372,7 @@ App.MainHostDetailsController = Em.Controller.extend({
     var componentsLength = Em.isNone(components) ? 0 : components.get('length');
     if (componentsLength > 0) {
       App.showConfirmationPopup(function () {
-        batchUtils.restartHostComponents(components, Em.I18n.t('rollingrestart.context.allOnSelectedHost').format(self.get('content.hostName')));
+        batchUtils.restartHostComponents(components, Em.I18n.t('rollingrestart.context.allOnSelectedHost').format(self.get('content.hostName')), "HOST");
       });
     }
   },
@@ -1566,7 +1582,7 @@ App.MainHostDetailsController = Em.Controller.extend({
     var self = this;
     return App.showConfirmationPopup(function () {
       var staleComponents = self.get('content.componentsWithStaleConfigs');
-      batchUtils.restartHostComponents(staleComponents, Em.I18n.t('rollingrestart.context.allWithStaleConfigsOnSelectedHost').format(self.get('content.hostName')));
+      batchUtils.restartHostComponents(staleComponents, Em.I18n.t('rollingrestart.context.allWithStaleConfigsOnSelectedHost').format(self.get('content.hostName')), "HOST");
     });
   },
 
@@ -1598,7 +1614,7 @@ App.MainHostDetailsController = Em.Controller.extend({
     });
     if (components.get('length') > 0) {
       return App.showConfirmationPopup(function () {
-        batchUtils.restartHostComponents(components, Em.I18n.t('rollingrestart.context.allClientsOnSelectedHost').format(self.get('content.hostName')));
+        batchUtils.restartHostComponents(components, Em.I18n.t('rollingrestart.context.allClientsOnSelectedHost').format(self.get('content.hostName')), "HOST");
       });
     }
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/6cd8a802/ambari-web/app/controllers/main/service.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service.js b/ambari-web/app/controllers/main/service.js
index d92a3c7..df8c9f7 100644
--- a/ambari-web/app/controllers/main/service.js
+++ b/ambari-web/app/controllers/main/service.js
@@ -120,11 +120,13 @@ App.MainServiceController = Em.ArrayController.extend({
     if (state == 'stopAllService') {
       data = '{"RequestInfo": {"context" :"' +
         App.BackgroundOperationsController.CommandContexts.STOP_ALL_SERVICES +
-        '"}, "Body": {"ServiceInfo": {"state": "INSTALLED"}}}';
+        '", "operation_level": {"level": "CLUSTER","cluster_name" : "' + App.get('clusterName') +
+        '"}}, "Body": {"ServiceInfo": {"state": "INSTALLED"}}}';
     } else {
       data = '{"RequestInfo": {"context" :"' +
         App.BackgroundOperationsController.CommandContexts.START_ALL_SERVICES +
-        '"}, "Body": {"ServiceInfo": {"state": "STARTED"}}}';
+        '", "operation_level": {"level": "CLUSTER","cluster_name" : "' + App.get('clusterName') +
+        '"}}, "Body": {"ServiceInfo": {"state": "STARTED"}}}';
     }
 
     App.ajax.send({

http://git-wip-us.apache.org/repos/asf/ambari/blob/6cd8a802/ambari-web/app/controllers/main/service/item.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/item.js b/ambari-web/app/controllers/main/service/item.js
index ac7d5b8..42b7828 100644
--- a/ambari-web/app/controllers/main/service/item.js
+++ b/ambari-web/app/controllers/main/service/item.js
@@ -313,7 +313,7 @@ App.MainServiceItemController = Em.Controller.extend({
     var self = this;
     if (this.get('content.isClientsOnly')) {
       return App.showConfirmationFeedBackPopup(function(query) {
-        batchUtils.restartHostComponents(self.get('content.hostComponents'), Em.I18n.t('rollingrestart.context.allForSelectedService').format(self.get('content.serviceName')), query);
+        batchUtils.restartHostComponents(self.get('content.hostComponents'), Em.I18n.t('rollingrestart.context.allForSelectedService').format(self.get('content.serviceName')),"SERVICE",  query);
       });
     }
   },

http://git-wip-us.apache.org/repos/asf/ambari/blob/6cd8a802/ambari-web/app/utils/ajax/ajax.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/ajax/ajax.js b/ambari-web/app/utils/ajax/ajax.js
index 6eef791..306ca16 100644
--- a/ambari-web/app/utils/ajax/ajax.js
+++ b/ambari-web/app/utils/ajax/ajax.js
@@ -71,7 +71,12 @@ var urls = {
         type: 'PUT',
         data: JSON.stringify({
           RequestInfo: {
-            "context": data.requestInfo
+            "context": data.requestInfo,
+            "operation_level": {
+              "level": "SERVICE",
+              "cluster_name" : data.clusterName,
+              "service_name" : data.serviceName
+            }
           },
           Body: {
             ServiceInfo: {
@@ -398,25 +403,6 @@ var urls = {
       };
     }
   },
-  'host.host_component.action': {
-    'real': '/clusters/{clusterName}/hosts/{hostName}/host_components/{componentName}',
-    'mock': '',
-    'type': 'PUT',
-    'format': function (data) {
-      return {
-        data: JSON.stringify({
-          RequestInfo: {
-            "context": data.context
-          },
-          Body: {
-            "HostRoles": {
-              "state": data.state
-            }
-          }
-        })
-      }
-    }
-  },
 
   'host.host_component.delete': {
     'real': '/clusters/{clusterName}/hosts/{hostName}/host_components/{componentName}',
@@ -474,18 +460,6 @@ var urls = {
     }
   },
 
-  'host.host_components.start': {
-    'real': '/clusters/{clusterName}/hosts/{hostName}/host_components',
-    'mock': '/data/wizard/deploy/poll_1.json',
-    'format': function(data) {
-      return {
-        type: 'PUT',
-        async: false,
-        data: data.data
-      }
-    }
-  },
-
   'host.host_component.install': {
     'real': '/clusters/{clusterName}/hosts/{hostName}/host_components/{componentName}',
     'mock': '/data/wizard/deploy/poll_1.json',
@@ -1775,7 +1749,8 @@ var urls = {
         data : JSON.stringify({
           "RequestInfo": {
             "command": "RESTART",
-            "context": data.context
+            "context": data.context,
+            "operation_level": data.operation_level
           },
           "Requests/resource_filters": data.resource_filters
         })
@@ -1964,7 +1939,12 @@ var urls = {
         data: JSON.stringify({
           RequestInfo: {
             context: data.requestInfo,
-            query: data.query
+            query: data.query,
+            operation_level: {
+              level: "HOST",
+              cluster_name: data.clusterName,
+              host_name: data.hostName
+            }
           },
           Body: {
             HostRoles: {

http://git-wip-us.apache.org/repos/asf/ambari/blob/6cd8a802/ambari-web/app/utils/batch_scheduled_requests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/batch_scheduled_requests.js b/ambari-web/app/utils/batch_scheduled_requests.js
index 2c872d0..e7d4824 100644
--- a/ambari-web/app/utils/batch_scheduled_requests.js
+++ b/ambari-web/app/utils/batch_scheduled_requests.js
@@ -89,7 +89,7 @@ module.exports = {
       if (staleConfigsOnly) {
         hostComponents = hostComponents.filterProperty('staleConfigs', true);
       }
-      this.restartHostComponents(hostComponents, context, query);
+      this.restartHostComponents(hostComponents, context, "SERVICE", query);
     }
   },
 
@@ -97,8 +97,10 @@ module.exports = {
    * Restart list of host components
    * @param {Ember.Enumerable} hostComponentsList list of host components should be restarted
    * @param {String} context message to show in BG popup
+   * @param {String} level - operation level, can be ("CLUSTER", "SERVICE", "HOST", "HOSTCOMPONENT")
+   * @param {String} query
    */
-  restartHostComponents: function(hostComponentsList, context, query) {
+  restartHostComponents: function(hostComponentsList, context, level, query) {
     context = context || Em.I18n.t('rollingrestart.context.default');
     /**
      * Format: {
@@ -108,6 +110,7 @@ module.exports = {
      * }
      */
     var componentToHostsMap = {};
+    var hosts = [];
     var componentServiceMap = App.QuickDataMapper.componentServiceMap();
     hostComponentsList.forEach(function(hc) {
       var componentName = hc.get('componentName');
@@ -115,6 +118,7 @@ module.exports = {
         componentToHostsMap[componentName] = [];
       }
       componentToHostsMap[componentName].push(hc.get('host.hostName'));
+      hosts.push(hc.get('host.hostName'));
     });
     var resource_filters = [];
     for (var componentName in componentToHostsMap) {
@@ -126,6 +130,12 @@ module.exports = {
         });
       }
     }
+      if(hostComponentsList.length > 0) {
+      var operation_level = this.getOperationLevelobject(level, hosts.uniq().join(","),
+          hostComponentsList[0].get("service.serviceName"), hostComponentsList[0].get("componentName"));
+    }
+
+
     if (resource_filters.length) {
       App.ajax.send({
         name: 'restart.hostComponents',
@@ -136,7 +146,8 @@ module.exports = {
         data: {
           context: context,
           resource_filters: resource_filters,
-          query: query
+          query: query,
+          operation_level: operation_level
         },
         success: 'successCallback',
         error: 'errorCallback'
@@ -145,6 +156,30 @@ module.exports = {
   },
 
   /**
+   * @param {String} level - operation level name, can be ("CLUSTER", "SERVICE", "HOST", "HOSTCOMPONENT")
+   * @param {String} hostName get host name or hostNames as String("host1,host2")
+   * @param {String} serviceName
+   * @param {String} componentName
+   * @returns {Object} {{level: *, cluster_name: *}} - operation level object
+   * @method getOperationLevelobject - create operation level object to be included into ajax query
+   */
+  getOperationLevelobject: function(level, hostName, serviceName, componentName) {
+    var operationLevel = {
+      "level": level,
+      "cluster_name": App.get("clusterName")
+    };
+    if (level === "HOST") {
+      operationLevel["host_name"] = hostName;
+    } else if (level === "SERVICE") {
+      operationLevel["service_name"] = serviceName;
+    } else {
+      operationLevel["host_name"] = hostName;
+      operationLevel["service_name"] = serviceName;
+      operationLevel["hostcomponent_name"] = componentName;
+    }
+    return operationLevel;
+  },
+  /**
    * Makes a REST call to the server requesting the rolling restart of the
    * provided host components.
    * @param {Array} restartHostComponents list of host components should be restarted

http://git-wip-us.apache.org/repos/asf/ambari/blob/6cd8a802/ambari-web/test/controllers/main/host/details_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/host/details_test.js b/ambari-web/test/controllers/main/host/details_test.js
index 3d6bb2a..4c0d29c 100644
--- a/ambari-web/test/controllers/main/host/details_test.js
+++ b/ambari-web/test/controllers/main/host/details_test.js
@@ -126,10 +126,42 @@ describe('App.MainHostDetailsController', function () {
   });
 
   describe('#getDataToSend()', function () {
+    var component = Em.Object.create({
+      componentName: 'comp1',
+      host: {
+        hostName: 'host1'
+      },
+      service: {
+        serviceName: 'serv1'
+      }
+    });
     it('should return correct query info', function () {
-      expect(controller.getDataToSend('STATE1', 'context')).to.eql({
+      controller.set("content.hostName", "host1");
+      expect(controller.getDataToSend('STATE1', 'context', component)).to.deep.eql({
         RequestInfo: {
-          "context": 'context'
+          "context": 'context',
+          "operation_level": {
+            "cluster_name": "tdk",
+            "host_name": "host1",
+            "hostcomponent_name": "comp1",
+            "service_name": "serv1",
+            "level": "HOST_COMPONENT"
+          }
+        },
+        Body: {
+          HostRoles: {
+            state: 'STATE1'
+          }
+        }
+      });
+      expect(controller.getDataToSend('STATE1', 'context', [component])).to.deep.eql({
+        RequestInfo: {
+          "context": 'context',
+          "operation_level": {
+            "cluster_name": "tdk",
+            "host_name": "host1",
+            "level": "HOST"
+          }
         },
         Body: {
           HostRoles: {


[2/2] git commit: AMBARI-5636 Unit test and refactoring for controllers/main/service/info/config.js part 1. (ababiichuk)

Posted by ab...@apache.org.
AMBARI-5636 Unit test and refactoring for controllers/main/service/info/config.js part 1. (ababiichuk)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/68020574
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/68020574
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/68020574

Branch: refs/heads/trunk
Commit: 68020574d540923c6c59ffabe0747d60d83e6144
Parents: 6cd8a80
Author: aBabiichuk <ab...@cybervisiontech.com>
Authored: Wed Apr 30 19:24:02 2014 +0300
Committer: aBabiichuk <ab...@cybervisiontech.com>
Committed: Wed Apr 30 19:24:02 2014 +0300

----------------------------------------------------------------------
 ambari-web/app/assets/test/tests.js             |   3 +-
 .../controllers/main/service/info/configs.js    | 110 ++-
 ambari-web/test/controllers/main/item_test.js   | 708 -------------------
 .../main/service/info/config_test.js            | 708 +++++++++++++++++++
 .../test/controllers/main/service/item_test.js  | 708 +++++++++++++++++++
 5 files changed, 1505 insertions(+), 732 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/68020574/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js
index 8bc38cf..6c8c0b7 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -54,7 +54,8 @@ require('test/controllers/main/service/add_controller_test');
 require('test/controllers/main/service/reassign_controller_test');
 require('test/controllers/main/dashboard_test');
 require('test/controllers/main/host_test');
-require('test/controllers/main/item_test');
+require('test/controllers/main/service/item_test');
+require('test/controllers/main/service/info/config_test');
 require('test/controllers/main/jobs_controller_test');
 require('test/controllers/main/jobs/hive_job_details_controller_test');
 require('test/controllers/main/service_test');

http://git-wip-us.apache.org/repos/asf/ambari/blob/68020574/ambari-web/app/controllers/main/service/info/configs.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/info/configs.js b/ambari-web/app/controllers/main/service/info/configs.js
index b693666..712665f 100644
--- a/ambari-web/app/controllers/main/service/info/configs.js
+++ b/ambari-web/app/controllers/main/service/info/configs.js
@@ -1358,6 +1358,18 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
 
   /**
    * Compares the loaded config values with the saving config values.
+   * @param {Object} loadedConfig -
+   * loadedConfig: {
+   *      configName1: "configValue1",
+   *      configName2: "configValue2"
+   *   }
+   * @param {Object} savingConfig
+   * savingConfig: {
+   *      configName1: "configValue1",
+   *      configName2: "configValue2"
+   *   }
+   * @returns {boolean}
+   * @method isConfigChanged
    */
   isConfigChanged: function (loadedConfig, savingConfig) {
     var changed = false;
@@ -1392,6 +1404,9 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
   /**
    * Saves configuration of a particular site. The provided data
    * contains the site name and tag to be used.
+   * @param {Object} data
+   * @return {bool}
+   * @method doPUTClusterConfigurationSite
    */
   doPUTClusterConfigurationSite: function (data) {
     App.ajax.send({
@@ -1416,11 +1431,23 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
    */
   doPUTClusterConfigurationSiteResult: null,
 
+  /**
+   * set doPUTClusterConfigurationSiteResult to true and write info to log
+   * @param {Object} data
+   * @method doPUTClusterConfigurationSiteSuccessCallback
+   */
   doPUTClusterConfigurationSiteSuccessCallback: function(data) {
     console.log("applyClusterConfigurationToSite(): In success for data:", data);
     this.set('doPUTClusterConfigurationSiteResult', true);
   },
 
+  /**
+   * set doPUTClusterConfigurationSiteResult to false and write info to log
+   * @param {Object} request
+   * @param {Object} ajaxOptions
+   * @param {String} error
+   * @method doPUTClusterConfigurationSiteSuccessCallback
+   */
   doPUTClusterConfigurationSiteErrorCallback: function(request, ajaxOptions, error) {
     console.log('applyClusterConfigurationToSite(): ERROR:', request.responseText, ", error=", error);
     this.set('doPUTClusterConfigurationSiteResult', false);
@@ -1440,8 +1467,9 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
   /**
    * create global site object
    * @param {String} tagName
-   * @param {Array} globalConfigs
-   * @return {Object}
+   * @param {Array} globalConfigs array of config objects
+   * @return {{"type": String, "tag": String, "properties": Object}}
+   * @method createGlobalSiteObj
    */
   createGlobalSiteObj: function (tagName, globalConfigs) {
     var heapsizeException = ['hadoop_heapsize', 'yarn_heapsize', 'nodemanager_heapsize', 'resourcemanager_heapsize', 'apptimelineserver_heapsize', 'jobhistory_heapsize'];
@@ -1465,7 +1493,8 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
   /**
    * create core site object
    * @param tagName
-   * @return {Object}
+   * @return {{"type": String, "tag": String, "properties": Object}}
+   * @method createCoreSiteObj
    */
   createCoreSiteObj: function (tagName) {
     var coreSiteObj = this.get('uiConfigs').filterProperty('filename', 'core-site.xml');
@@ -1521,15 +1550,6 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
         return App.config.escapeXMLCharacters(value);
     }
   },
-  /**
-   * return either specific url for request if testMode is false or testUrl
-   * @param testUrl
-   * @param url
-   * @return {*}
-   */
-  getUrl: function (testUrl, url) {
-    return (App.testMode) ? testUrl : App.apiPrefix + '/clusters/' + App.router.getClusterName() + url;
-  },
 
   /**
    * Adds host name of master component to global config;
@@ -1650,6 +1670,12 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
     }
   },
 
+  /**
+   * get hostName of component
+   * @param {String} componentName
+   * @return {String} hostName
+   * @method getMasterComponentHostValue
+   */
   getMasterComponentHostValue: function(componentName) {
     var component = this.get('content.hostComponents').findProperty('componentName', componentName);
     return component ? component.get('host.hostName') : false;
@@ -1657,10 +1683,11 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
   /**
    * Provides service component name and display-name information for
    * the current selected service.
+   * @return {Em.Array} validComponents - array of valid components
+   * @method getCurrentServiceComponents
    */
   getCurrentServiceComponents: function () {
-    var service = this.get('content');
-    var components = service.get('hostComponents');
+    var components = this.get('content.hostComponents');
     var validComponents = Ember.A([]);
     var seenComponents = {};
     components.forEach(function (component) {
@@ -1678,10 +1705,19 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
     return validComponents;
   }.property('content'),
 
+  /**
+   * trigger loadStep
+   * @method loadStep
+   */
   doCancel: function () {
     this.loadStep();
   },
 
+  /**
+   * trigger restartAllServiceHostComponents(batchUtils) if confirmed in popup
+   * @method restartAllStaleConfigComponents
+   * @return App.showConfirmationFeedBackPopup
+   */
   restartAllStaleConfigComponents: function() {
     var self = this;
     var serviceDisplayName = this.get('content.displayName');
@@ -1690,16 +1726,24 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
       confirmButton: Em.I18n.t('services.service.restartAll.confirmButton'),
       additionalWarningMsg: this.get('content.passiveState') === 'OFF' ? Em.I18n.t('services.service.restartAll.warningMsg.turnOnMM').format(serviceDisplayName): null
     });
-    App.showConfirmationFeedBackPopup(function(query) {
+    return App.showConfirmationFeedBackPopup(function(query) {
       var selectedService = self.get('content.id');
       batchUtils.restartAllServiceHostComponents(selectedService, true, query);
     }, bodyMessage);
   },
 
+  /**
+   * trigger launchHostComponentRollingRestart(batchUtils)
+   * @method rollingRestartStaleConfigSlaveComponents
+   */
   rollingRestartStaleConfigSlaveComponents: function(componentName) {
     batchUtils.launchHostComponentRollingRestart(componentName.context, this.get('content.displayName'), this.get('content.passiveState') === "ON", true);
   },
 
+  /**
+   * trigger showItemsShouldBeRestarted popup with hosts that requires resetart
+   * @method showHostsShouldBeRestarted
+   */
   showHostsShouldBeRestarted: function() {
     var hosts = [];
     for(var hostName in this.get('content.restartRequiredHostsAndComponents')) {
@@ -1709,6 +1753,11 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
     hosts = hosts.join(', ');
     this.showItemsShouldBeRestarted(hosts, Em.I18n.t('service.service.config.restartService.shouldBeRestarted').format(hostsText));
   },
+
+  /**
+   * trigger showItemsShouldBeRestarted popup with components that requires resetart
+   * @method showComponentsShouldBeRestarted
+   */
   showComponentsShouldBeRestarted: function() {
     var rhc = this.get('content.restartRequiredHostsAndComponents');
     var hostsComponets = [];
@@ -1758,6 +1807,11 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
     });
   },
 
+  /**
+   * add new overridden property to config property object
+   * @param {object} serviceConfigProperty - config property object
+   * @method addOverrideProperty
+   */
   addOverrideProperty: function(serviceConfigProperty) {
     var overrides = serviceConfigProperty.get('overrides');
     if (!overrides) {
@@ -1774,6 +1828,10 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
     overrides.pushObject(newSCP);
   },
 
+  /**
+   * trigger manageConfigurationGroups
+   * @method manageConfigurationGroup
+   */
   manageConfigurationGroup: function () {
     this.manageConfigurationGroups();
   },
@@ -1783,7 +1841,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
     var serviceName = serviceData.get('serviceName');
     var displayName = serviceData.get('displayName');
     App.router.get('manageConfigGroupsController').set('isInstaller', !!controller);
-    App.ModalPopup.show({
+    return App.ModalPopup.show({
       header: Em.I18n.t('services.service.config_groups_popup.header').format(displayName),
       bodyClass: App.MainServiceManageConfigGroupView.extend({
         serviceName: serviceName,
@@ -1901,6 +1959,11 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
     });
   },
 
+  /**
+   * If user chabges cfg group if some configs was changed popup with propose to save changes must be shown
+   * @param {object} event - triggered event for selecting another config-group
+   * @method selectConfigGroup
+   */
   selectConfigGroup: function (event) {
     if (!this.get('isInit')) {
       if (this.hasUnsavedChanges()) {
@@ -1923,32 +1986,33 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
    * If some configs are changed and user navigates away or select another config-group, show this popup with propose to save changes
    * @param {String} path
    * @param {object} event - triggered event for selecting another config-group
+   * @method showSavePopup
    */
   showSavePopup: function (path, event) {
-    var _this = this;
-    App.ModalPopup.show({
+    var self = this;
+    return App.ModalPopup.show({
       header: Em.I18n.t('common.warning'),
       body: Em.I18n.t('services.service.config.exitPopup.body'),
       footerClass: Ember.View.extend({
         templateName: require('templates/main/service/info/save_popup_footer'),
         isSaveDisabled: function() {
-          return _this.get('isSubmitDisabled');
+          return self.get('isSubmitDisabled');
         }.property()
       }),
       primary: Em.I18n.t('common.save'),
       secondary: Em.I18n.t('common.cancel'),
       onSave: function () {
-        _this.restartServicePopup();
+        self.restartServicePopup();
         this.hide();
       },
       onDiscard: function () {
         if (path) {
-          _this.set('forceTransition', true);
+          self.set('forceTransition', true);
           App.router.route(path);
         } else if (event) {
           // Prevent multiple popups
-          _this.set('hash', _this.getHash());
-          _this.selectConfigGroup(event);
+          self.set('hash', self.getHash());
+          self.selectConfigGroup(event);
         }
         this.hide();
       },

http://git-wip-us.apache.org/repos/asf/ambari/blob/68020574/ambari-web/test/controllers/main/item_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/item_test.js b/ambari-web/test/controllers/main/item_test.js
deleted file mode 100644
index f7b43ed..0000000
--- a/ambari-web/test/controllers/main/item_test.js
+++ /dev/null
@@ -1,708 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-App = require('app');
-require('ember');
-require('models/host_component')
-require('views/common/modal_popup');
-require('mixins/common/userPref');
-require('controllers/application');
-require('controllers/global/background_operations_controller');
-require('controllers/global/cluster_controller');
-require('controllers/main/service/reassign_controller')
-require('controllers/main/service/item');
-var batchUtils = require('utils/batch_scheduled_requests');
-
-describe('App.MainServiceItemController', function () {
-
-  describe('#setStartStopState', function () {
-    var tests = [
-      {
-        serviceController: {
-          serviceName: "YARN"
-        },
-        backgroundOperationsController: {
-          services: [
-            {
-              isRunning: true,
-              dependentService: "ALL_SERVICES"
-            }
-          ]
-        },
-        isPending: true,
-        m: 'operaion is active because all services are running'
-      },
-      {
-        serviceController: {
-          serviceName: "HBASE"
-        },
-        backgroundOperationsController: {
-          services: [
-            {
-              isRunning: true,
-              dependentService: "HBASE"
-            }
-          ]
-        },
-        isPending: true,
-        m: 'operaion is active button because current service is running'
-      },
-      {
-        serviceController: {
-          serviceName: "HDFS"
-        },
-        backgroundOperationsController: {
-          services: [
-
-          ]
-        },
-        isPending: true,
-        m: 'pending is true - backgroundOperationsController.services is empty'
-      },
-      {
-        serviceController: {
-          serviceName: "HBASE"
-        },
-        backgroundOperationsController: {
-          services: [
-            {
-              isRunning: false,
-              dependentService: "ALL_SERVICES"
-            }
-          ]
-        },
-        isPending: false,
-        m: 'pending is false - operation is not running'
-      },
-      {
-        serviceController: {
-          serviceName: "HBASE"
-        },
-        backgroundOperationsController: {
-          services: [
-            {
-              isRunning: true,
-              dependentService: "HDFS"
-            }
-          ]
-        },
-        isPending: false,
-        m: 'pending is false - current service is not running'
-      }
-    ];
-
-
-    tests.forEach(function (test) {
-      it(test.m, function () {
-        var backgroundOperationsController = App.BackgroundOperationsController.create();
-        backgroundOperationsController.set('services', []);
-        test.backgroundOperationsController.services.forEach(function (service) {
-          backgroundOperationsController.get('services').push(service);
-        });
-        backgroundOperationsController.set("serviceTimestamp", new Date().getTime());
-        App.router.set('backgroundOperationsController', backgroundOperationsController);
-        var mainServiceItemController = App.MainServiceItemController.create({content: {serviceName: test.serviceController.serviceName}});
-        mainServiceItemController.setStartStopState();
-        expect(mainServiceItemController.get('isPending')).to.equal(test.isPending);
-      });
-    })
-  });
-
-  describe('#reassignMaster()', function () {
-    var v;
-    var tests = [
-      {
-        host_components: [
-          {component_name: "RESOURCEMANGER"}
-        ],
-        conponentName: "RESOURCEMANGER",
-        result: true,
-        m: 'run reassignMaster'
-      },
-      {
-        host_components: [
-          {component_name: "RESOURCEMANGER"}
-        ],
-        conponentName: "DATANODE",
-        result: false,
-        m: 'don\t run reassignMaster'
-      }
-    ];
-
-    tests.forEach(function (test) {
-      var reassignMasterController = App.ReassignMasterController.create({currentStep: ''});
-      beforeEach(function () {
-        sinon.spy(reassignMasterController, 'saveComponentToReassign');
-        sinon.spy(reassignMasterController, 'getSecurityStatus');
-        sinon.spy(reassignMasterController, 'setCurrentStep');
-        App.router.transitionTo = Em.K;
-      });
-      afterEach(function () {
-        reassignMasterController.saveComponentToReassign.restore();
-        reassignMasterController.getSecurityStatus.restore();
-        reassignMasterController.setCurrentStep.restore();
-        App.router.transitionTo = v;
-      });
-      it(test.m, function () {
-        v = App.router.transitionTo;
-        var mainServiceItemController = App.MainServiceItemController.create({});
-        App.router.set('reassignMasterController', reassignMasterController);
-        App.store.loadMany(App.HostComponent, test.host_components);
-        mainServiceItemController.reassignMaster(test.conponentName);
-        expect(reassignMasterController.saveComponentToReassign.calledOnce).to.equal(test.result);
-        expect(reassignMasterController.getSecurityStatus.calledOnce).to.equal(test.result);
-        expect(reassignMasterController.setCurrentStep.calledOnce).to.equal(test.result);
-      });
-    }, this);
-  });
-
-  describe("#updateService", function () {
-
-    var tests = [
-      {
-        params: {
-          passive_state: "ON"
-        },
-        m: "turn on passive"
-      },
-      {
-        params: {
-          passive_state: "OFF"
-        },
-        m: "turn off passive"
-      }
-    ];
-    tests.forEach(function (test) {
-      it(test.m, function () {
-        var clusterController = App.ClusterController.create();
-        App.router.set('clusterController', clusterController);
-        var mainServiceItemController = App.MainServiceItemController.create({content: {passiveState: "ON"}});
-        mainServiceItemController.updateService(null, null, test.params);
-        expect(mainServiceItemController.get('content.passiveState')).to.equal(test.params.passive_state);
-      });
-    });
-  });
-
-  describe("#doAction", function () {
-
-    var el = document.createElement("BUTTON");
-    el.disabled = false;
-    var tests = [
-      {
-        event: {
-          target: el,
-          context: {
-            action: 'runSmokeTest'
-          }
-        },
-        m: "run runSmokeTest"
-      },
-      {
-        event: {
-          target: el,
-          context: {
-            action: 'refreshConfigs'
-          }
-        },
-        m: "run refreshConfigs"
-      },
-      {
-        event: {
-          target: el,
-          context: {
-            action: 'restartAllHostComponents'
-          }
-        },
-        m: "run restartAllHostComponents"
-      },
-      {
-        event: {
-          target: el,
-          context: {
-            action: 'rollingRestart'
-          }
-        },
-        m: "run rollingRestart"
-      }
-    ];
-
-    tests.forEach(function (test) {
-      var mainServiceItemController = App.MainServiceItemController.create({});
-      mainServiceItemController.set(test.event.context.action, Em.K);
-      beforeEach(function () {
-        sinon.spy(mainServiceItemController, test.event.context.action);
-      });
-      afterEach(function () {
-        mainServiceItemController[test.event.context.action].restore();
-      });
-      it(test.m, function () {
-        mainServiceItemController.doAction(test.event);
-        expect(mainServiceItemController[test.event.context.action].calledOnce).to.equal(!test.event.target.disabled);
-      });
-    });
-  });
-
-  describe("#startStopPopupPrimary", function () {
-
-
-    var tests = [
-      {
-        data: {
-          "serviceName": "HDFS",
-          "state": "STARTED",
-          "query": Em.Object.create({ServiceInfo: "FAIL"})
-        },
-        request: {
-          "RequestInfo": {
-            "context": "_PARSE_.START.HDFS"
-          },
-          "Body": {
-            "ServiceInfo": {
-              "state": "STARTED"
-            }
-          }
-        },
-        m: "Start HDFS"
-      },
-      {
-        data: {
-          "serviceName": "YARN",
-          "state": "STOPPED",
-          "query": Em.Object.create({ServiceInfo: "FAIL"})
-        },
-        request: {
-          "RequestInfo": {
-            "context": "_PARSE_.STOP.YARN"
-          },
-          "Body": {
-            "ServiceInfo": {
-              "state": "STOPPED"
-            }
-          }
-        },
-        m: "Stop YARN"
-      }
-    ];
-
-    beforeEach(function () {
-      sinon.spy($, 'ajax');
-    });
-
-    afterEach(function () {
-      $.ajax.restore();
-    });
-
-
-    tests.forEach(function (test) {
-      it('', function () {
-        var mainServiceItemController = App.MainServiceItemController.create({content: {serviceName: test.data.serviceName}});
-        mainServiceItemController.startStopPopupPrimary(test.data.state, test.data.query);
-        expect($.ajax.calledOnce).to.equal(true);
-
-        expect(JSON.parse($.ajax.args[0][0].data).Body.ServiceInfo.state).to.equal(test.request.Body.ServiceInfo.state);
-        expect(JSON.parse($.ajax.args[0][0].data).RequestInfo.context).to.equal(test.request.RequestInfo.context);
-
-        expect(mainServiceItemController.get('isStopDisabled')).to.equal(true);
-        expect(mainServiceItemController.get('isStartDisabled')).to.equal(true);
-      });
-    });
-
-
-  });
-
-  describe("#startStopPopupSuccessCallback", function () {
-
-    var data = {
-      Requests: true
-    };
-    var params = Em.Object.create({
-      query: Em.Object.create()
-    });
-    var ajaxOptions = {
-      data: '{"RequestInfo":{"context":"_PARSE_.STOP.ZOOKEEPER"},"Body":{"ServiceInfo":{"state":"INSTALLED"}}}'
-    };
-
-    var content = {
-      workStatus: "",
-      hostComponents: [
-        {
-          workStatus: ""
-        }
-      ]
-    };
-
-    var mainServiceItemController = App.MainServiceItemController.create({content: content});
-    var applicationController = App.ApplicationController.create(App.UserPref, {});
-    var clusterController = App.ClusterController.create({loadUpdatedStatusDelayed: Em.K});
-    var backgroundOperationsController = App.BackgroundOperationsController.create({showPopup: Em.K});
-    App.testMode = false;
-    beforeEach(function () {
-      App.testMode = false;
-      sinon.spy(clusterController, "loadUpdatedStatusDelayed");
-    });
-    afterEach(function () {
-      clusterController.loadUpdatedStatusDelayed.restore();
-      App.testMode = true;
-    });
-    it("open bgo popup", function () {
-      App.router.set('applicationController', applicationController);
-      App.router.set('clusterController', clusterController);
-      App.router.set('backgroundOperationsController', backgroundOperationsController);
-      mainServiceItemController.startStopPopupSuccessCallback(data, ajaxOptions, params);
-      expect(clusterController.loadUpdatedStatusDelayed.calledOnce).to.equal(true);
-    })
-  });
-
-
-  describe("#startService , #stopService", function () {
-    var mainServiceItemController = App.MainServiceItemController.create({startStopPopup: Em.K});
-    beforeEach(function () {
-      sinon.spy(mainServiceItemController, "startStopPopup");
-    });
-    afterEach(function () {
-      mainServiceItemController.startStopPopup.restore();
-    });
-    it("start service", function () {
-      mainServiceItemController.startService({});
-      expect(mainServiceItemController.startStopPopup.calledWith({},App.HostComponentStatus.started)).to.equal(true);
-    });
-    it("stop service", function () {
-      mainServiceItemController.stopService({});
-      expect(mainServiceItemController.startStopPopup.calledWith({},App.HostComponentStatus.stopped)).to.equal(true);
-    });
-  });
-
-
-  describe("#turnOnOffPassive", function () {
-    var mainServiceItemController = App.MainServiceItemController.create({turnOnOffPassiveRequest: Em.K});
-    beforeEach(function () {
-      sinon.spy(mainServiceItemController, "turnOnOffPassiveRequest");
-    });
-    afterEach(function () {
-      mainServiceItemController.turnOnOffPassiveRequest.restore();
-    });
-    it("turns on/off passive mode for service", function () {
-      mainServiceItemController.turnOnOffPassive({}).onPrimary();
-      expect(mainServiceItemController.turnOnOffPassiveRequest.calledOnce).to.equal(true);
-    });
-  });
-
-  describe("#runSmokeTest", function () {
-    var tests = [
-      {
-        content: {
-          id: "YARN",
-          service_name: "YARN",
-          work_status: "STARTED"
-        },
-        startSmoke: true,
-        serviceName: "MAPREDUCE2",
-        m: "don't run smoke test primary for MAPREDUCE2"
-      },
-      {
-        content: {
-          id: "YARN",
-          service_name: "YARN",
-          work_status: "STOPPED"
-        },
-        startSmoke: false,
-        serviceName: "MAPREDUCE2",
-        m: "run smoke test primary for MAPREDUCE2"
-      },
-      {
-        m: "run smoke test primary for all services (not MAPREDUCE2)",
-        startSmoke: true,
-        default: true
-      }
-    ];
-
-    tests.forEach(function (test) {
-      var mainServiceItemController = test.default ? App.MainServiceItemController.create({runSmokeTestPrimary: Em.K}) :
-          App.MainServiceItemController.create({content: {serviceName: test.serviceName}, runSmokeTestPrimary: Em.K});
-      beforeEach(function () {
-        sinon.spy(mainServiceItemController, "runSmokeTestPrimary");
-      });
-      afterEach(function () {
-        mainServiceItemController.runSmokeTestPrimary.restore();
-      });
-      it(test.m, function () {
-        if (!test.default) {
-          App.store.load(App.Service, test.content);
-        }
-        mainServiceItemController.runSmokeTest({}).onPrimary();
-        expect(mainServiceItemController.runSmokeTestPrimary.calledOnce).to.equal(test.startSmoke);
-      });
-    });
-  });
-
-  describe("#refreshConfigs", function () {
-    var temp = batchUtils.restartHostComponents;
-    beforeEach(function () {
-      batchUtils.restartHostComponents = Em.K;
-      sinon.spy(batchUtils, "restartHostComponents");
-    });
-    afterEach(function () {
-      batchUtils.restartHostComponents.restore();
-      batchUtils.restartHostComponents = temp;
-    });
-    var tests = [
-      {
-        isClientsOnly: true,
-        m: "run refresh for clients"
-      },
-      {
-        isClientsOnly: false,
-        m: "don't run refresh for non clients"
-      }
-    ];
-    tests.forEach(function (test) {
-      var mainServiceItemController = App.MainServiceItemController.create({content: {isClientsOnly: test.isClientsOnly}});
-      it(test.m, function () {
-        if (test.isClientsOnly) {
-          mainServiceItemController.refreshConfigs().onPrimary();
-        } else {
-          mainServiceItemController.refreshConfigs();
-        }
-        expect(batchUtils.restartHostComponents.calledOnce).to.equal(test.isClientsOnly);
-      });
-    }, this);
-  });
-
-  describe("#startStopPopup", function () {
-    var el = document.createElement("BUTTON");
-    el.disabled = false;
-    var event = {
-      target: el
-    }
-    var mainServiceItemController = App.MainServiceItemController.create({content: {serviceName: "HDFS"}});
-    beforeEach(function () {
-      sinon.spy(mainServiceItemController, "startStopPopupPrimary");
-    });
-    afterEach(function () {
-      mainServiceItemController.startStopPopupPrimary.restore();
-    });
-    it("start start/stop service popup", function () {
-      mainServiceItemController.startStopPopup(event, "").onPrimary();
-      expect(mainServiceItemController.startStopPopupPrimary.calledOnce).to.equal(true);
-    });
-  });
-
-  describe("#restartAllHostComponents", function () {
-    var temp = batchUtils.restartAllServiceHostComponents;
-    beforeEach(function () {
-      batchUtils.restartAllServiceHostComponents = Em.K;
-      sinon.spy(batchUtils, "restartAllServiceHostComponents");
-    });
-    afterEach(function () {
-      batchUtils.restartAllServiceHostComponents.restore();
-      batchUtils.restartAllServiceHostComponents = temp;
-    });
-
-    var mainServiceItemController = App.MainServiceItemController.create({content: {displayName: "HDFS"}});
-
-    it("start restartAllHostComponents for service", function () {
-      mainServiceItemController.restartAllHostComponents({}).onPrimary();
-      expect(batchUtils.restartAllServiceHostComponents.calledOnce).to.equal(true);
-    });
-  });
-
-  describe("#rollingRestart", function () {
-    var temp = batchUtils.launchHostComponentRollingRestart;
-    beforeEach(function () {
-      batchUtils.launchHostComponentRollingRestart = Em.K;
-      sinon.spy(batchUtils, "launchHostComponentRollingRestart");
-    });
-    afterEach(function () {
-      batchUtils.launchHostComponentRollingRestart.restore();
-      batchUtils.launchHostComponentRollingRestart = temp;
-    });
-
-    var mainServiceItemController = App.MainServiceItemController.create();
-
-    it("start restartAllHostComponents for service", function () {
-      mainServiceItemController.rollingRestart();
-      expect(batchUtils.launchHostComponentRollingRestart.calledOnce).to.equal(true);
-    });
-  });
-
-  describe("#isStartDisabled", function () {
-    var tests = [
-      {
-        content: {
-          healthStatus: 'red'
-        },
-        isPending: true,
-        disabled: true,
-        m: "disabled because of pending"
-      },
-      {
-        content: {
-          healthStatus: 'green'
-        },
-        isPending: false,
-        disabled: true,
-        m: "disabled because healthStatus is not red"
-      },
-      {
-        content: {
-          healthStatus: 'red'
-        },
-        isPending: false,
-        disabled: false,
-        m: "enabled because healthStatus is red and pending is false"
-      }
-    ];
-    tests.forEach(function (test) {
-      it(test.m, function () {
-        var mainServiceItemController = App.MainServiceItemController.create({content: {healthStatus: test.content.healthStatus}, isPending: test.isPending});
-        expect(mainServiceItemController.get('isStartDisabled')).to.equal(test.disabled);
-      });
-    });
-  });
-
-  describe("#isSopDisabled", function () {
-    var tests = [
-      {
-        content: {
-          healthStatus: 'red'
-        },
-        isPending: true,
-        disabled: true,
-        m: "disabled because of pending"
-      },
-      {
-        content: {
-          healthStatus: 'green'
-        },
-        isPending: false,
-        disabled: false,
-        m: "enabled because healthStatus is green and pending is false"
-      },
-      {
-        content: {
-          healthStatus: 'red'
-        },
-        isPending: false,
-        disabled: true,
-        m: "disabled because healthStatus is not green"
-      }
-    ];
-    tests.forEach(function (test) {
-      it(test.m, function () {
-        var mainServiceItemController = App.MainServiceItemController.create({content: test.content, isPending: test.isPending});
-        expect(mainServiceItemController.get('isStopDisabled')).to.equal(test.disabled);
-      });
-    });
-  });
-
-  describe("#runRebalancer", function () {
-    it("run rebalancer", function () {
-      var mainServiceItemController = App.MainServiceItemController.create({content: {runRebalancer: false}});
-      mainServiceItemController.runRebalancer().onPrimary();
-      expect(mainServiceItemController.get("content.runRebalancer")).to.equal(true);
-    });
-  });
-
-  describe("#runCompaction", function () {
-    it("run compaction", function () {
-      var mainServiceItemController = App.MainServiceItemController.create({content: {runCompaction: false}});
-      mainServiceItemController.runCompaction().onPrimary();
-      expect(mainServiceItemController.get("content.runCompaction")).to.equal(true);
-    });
-  });
-
-  describe("#turnOnOffPassiveRequest", function () {
-    var tests = [
-      {
-        data: {
-          "requestInfo": 'Turn On Maintenance Mode',
-          "serviceName" : "HDFS",
-          "passive_state": "ON"
-        },
-        RequestInfo: {
-          "context": 'Turn On Maintenance Mode'
-        },
-        Body: {
-          ServiceInfo: {
-            maintenance_state: "ON"
-          }
-        }
-      }
-    ];
-
-    beforeEach(function () {
-      sinon.spy($, 'ajax');
-    });
-
-    afterEach(function () {
-      $.ajax.restore();
-    });
-
-    tests.forEach(function (test) {
-      it('send request to turn on passive state', function () {
-        var mainServiceItemController = App.MainServiceItemController.create({content: {serviceName: test.data.serviceName}});
-        mainServiceItemController.turnOnOffPassiveRequest(test.data.passive_state, test.data.requestInfo);
-        expect($.ajax.calledOnce).to.equal(true);
-
-        expect(JSON.parse($.ajax.args[0][0].data).Body.ServiceInfo.maintenance_state).to.equal(test.Body.ServiceInfo.maintenance_state);
-        expect(JSON.parse($.ajax.args[0][0].data).RequestInfo.context).to.equal(test.RequestInfo.context);
-      });
-    });
-  });
-
-  describe("#runSmokeTestPrimary", function () {
-    var tests = [
-      {
-        data: {
-          'serviceName': "HDFS",
-          'displayName': "HDFS",
-          'query': "test"
-        },
-        "RequestInfo": {
-          "context": "HDFS Service Check",
-          "command" : "HDFS_SERVICE_CHECK"
-        },
-        "Requests/resource_filters": [{"service_name" : "HDFS"}]
-      }
-    ];
-    tests.forEach(function (test) {
-
-    var mainServiceItemController = App.MainServiceItemController.create({content: {serviceName: test.data.serviceName,
-      displayName: test.data.displayName}});
-    beforeEach(function () {
-      mainServiceItemController.set("runSmokeTestErrorCallBack", Em.K);
-      mainServiceItemController.set("runSmokeTestSuccessCallBack", Em.K);
-      sinon.spy($, 'ajax');
-    });
-
-    afterEach(function () {
-      $.ajax.restore();
-    });
-
-      it('send request to run smoke test', function () {
-
-        mainServiceItemController.runSmokeTestPrimary(test.data.query);
-        expect($.ajax.calledOnce).to.equal(true);
-
-        expect(JSON.parse($.ajax.args[0][0].data).RequestInfo.context).to.equal(test.RequestInfo.context);
-        expect(JSON.parse($.ajax.args[0][0].data).RequestInfo.command).to.equal(test.RequestInfo.command);
-        expect(JSON.parse($.ajax.args[0][0].data)["Requests/resource_filters"][0].serviceName).to.equal(test["Requests/resource_filters"][0].serviceName);
-      });
-    });
-  });
-});

http://git-wip-us.apache.org/repos/asf/ambari/blob/68020574/ambari-web/test/controllers/main/service/info/config_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/service/info/config_test.js b/ambari-web/test/controllers/main/service/info/config_test.js
new file mode 100644
index 0000000..b701a05
--- /dev/null
+++ b/ambari-web/test/controllers/main/service/info/config_test.js
@@ -0,0 +1,708 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+require('controllers/main/service/info/configs');
+var batchUtils = require('utils/batch_scheduled_requests');
+var mainServiceInfoConfigsController = null;
+describe("App.MainServiceInfoConfigsController", function () {
+
+  beforeEach(function () {
+    mainServiceInfoConfigsController = App.MainServiceInfoConfigsController.create({});
+  });
+
+  describe("#showSavePopup", function () {
+    var tests = [
+      {
+        path: false,
+        event: false,
+        action: "onSave",
+        m: "save configs without path/event",
+        results: [
+          {
+            method: "restartServicePopup",
+            called: true
+          },
+          {
+            method: "selectConfigGroup",
+            called: false
+          }
+        ]
+      },
+      {
+        path: true,
+        event: true,
+        action: "onSave",
+        m: "save configs with path/event",
+        results: [
+          {
+            method: "restartServicePopup",
+            called: true
+          },
+          {
+            method: "selectConfigGroup",
+            called: false
+          }
+        ]
+      },
+      {
+        path: false,
+        event: false,
+        action: "onDiscard",
+        m: "discard changes without path/event",
+        results: [
+          {
+            method: "restartServicePopup",
+            called: false
+          },
+          {
+            method: "selectConfigGroup",
+            called: false
+          }
+        ]
+      },
+      {
+        path: false,
+        event: true,
+        action: "onDiscard",
+        m: "discard changes with event",
+        results: [
+          {
+            method: "restartServicePopup",
+            called: false
+          },
+          {
+            method: "selectConfigGroup",
+            called: true
+          },
+          {
+            field: "hash",
+            value: "hash"
+          }
+        ]
+      },
+      {
+        path: true,
+        event: false,
+        action: "onDiscard",
+        m: "discard changes with path",
+        results: [
+          {
+            method: "restartServicePopup",
+            called: false
+          },
+          {
+            method: "selectConfigGroup",
+            called: false
+          },
+          {
+            field: "forceTransition",
+            value: true
+          }
+        ]
+      }
+    ];
+
+    var rRoute = App.router.route;
+    beforeEach(function () {
+      sinon.stub(mainServiceInfoConfigsController, "restartServicePopup", Em.K);
+      sinon.stub(mainServiceInfoConfigsController, "selectConfigGroup", Em.K);
+      sinon.stub(mainServiceInfoConfigsController, "getHash", function () {
+        return "hash"
+      });
+      App.router.route = Em.K;
+    });
+    afterEach(function () {
+      mainServiceInfoConfigsController.restartServicePopup.restore();
+      mainServiceInfoConfigsController.selectConfigGroup.restore();
+      mainServiceInfoConfigsController.getHash.restore();
+      App.router.route = rRoute;
+    });
+
+    tests.forEach(function (t) {
+      t.results.forEach(function (r) {
+        it(t.m + " " + r.method + " " + r.field, function () {
+          mainServiceInfoConfigsController.showSavePopup(t.path, t.event)[t.action]();
+          if (r.method) {
+            expect(mainServiceInfoConfigsController[r.method].calledOnce).to.equal(r.called);
+          } else if (r.field) {
+            expect(mainServiceInfoConfigsController.get(r.field)).to.equal(r.value);
+          }
+        }, this);
+      });
+    }, this);
+  });
+
+  describe("#hasUnsavedChanges", function () {
+    beforeEach(function () {
+      sinon.stub(mainServiceInfoConfigsController, "getHash", function () {
+        return "hash"
+      });
+    });
+    afterEach(function () {
+      mainServiceInfoConfigsController.getHash.restore();
+    });
+
+    it("with unsaved", function () {
+      mainServiceInfoConfigsController.set("hash", "hash1");
+      expect(mainServiceInfoConfigsController.hasUnsavedChanges()).to.equal(true);
+    });
+
+    it("without unsaved", function () {
+      mainServiceInfoConfigsController.set("hash", "hash");
+      expect(mainServiceInfoConfigsController.hasUnsavedChanges()).to.equal(false);
+    });
+  });
+
+  describe("#selectConfigGroup", function () {
+
+    var tests = [
+      {
+        event: {
+          context: "cfgGroup"
+        },
+        isInit: true,
+        showPopup: false,
+        m: "setup new cfg group"
+      },
+      {
+        event: {
+          context: "cfgGroup"
+        },
+        isInit: false,
+        hash: "hash",
+        showPopup: false,
+        m: "setup new cfg group, has some changes"
+      },
+      {
+        event: {
+          context: "cfgGroup"
+        },
+        isInit: false,
+        hash: "hash1",
+        showPopup: true,
+        m: "show popup, doesn't setup new cfg group"
+      }
+    ];
+
+    beforeEach(function () {
+      sinon.stub(mainServiceInfoConfigsController, "showSavePopup", Em.K);
+      sinon.stub(mainServiceInfoConfigsController, "getHash", function () {
+        return "hash"
+      });
+      sinon.stub(mainServiceInfoConfigsController, "onConfigGroupChange", Em.K);
+    });
+    afterEach(function () {
+      mainServiceInfoConfigsController.showSavePopup.restore();
+      mainServiceInfoConfigsController.getHash.restore();
+      mainServiceInfoConfigsController.onConfigGroupChange.restore();
+    });
+    tests.forEach(function (t) {
+      it(t.m, function () {
+        mainServiceInfoConfigsController.set("isInit", t.isInit);
+        mainServiceInfoConfigsController.set("hash", t.hash);
+        mainServiceInfoConfigsController.selectConfigGroup(t.event);
+        if (!t.showPopup) {
+          expect(mainServiceInfoConfigsController.get("selectedConfigGroup")).to.equal(t.event.context);
+          expect(mainServiceInfoConfigsController.showSavePopup.calledOnce).to.equal(false);
+        } else {
+          expect(mainServiceInfoConfigsController.showSavePopup.calledWith(null, t.event)).to.equal(true);
+        }
+      });
+    });
+
+  });
+
+  describe("#manageConfigurationGroup", function () {
+    beforeEach(function () {
+      sinon.stub(mainServiceInfoConfigsController, "manageConfigurationGroups", Em.K);
+    });
+    afterEach(function () {
+      mainServiceInfoConfigsController.manageConfigurationGroups.restore();
+    });
+    it("run manageConfigurationGroups", function () {
+      mainServiceInfoConfigsController.manageConfigurationGroup();
+      expect(mainServiceInfoConfigsController.manageConfigurationGroups.calledOnce).to.equal(true);
+    });
+  });
+
+  describe("#addOverrideProperty", function () {
+    var serviceConfigProperty = Em.Object.create({
+      overrides: []
+    });
+
+    var newSCP = App.ServiceConfigProperty.create(serviceConfigProperty);
+    newSCP.set('value', '');
+    newSCP.set('isOriginalSCP', false);
+    newSCP.set('parentSCP', serviceConfigProperty);
+    newSCP.set('isEditable', true);
+
+    it("add new overridden property", function () {
+      mainServiceInfoConfigsController.addOverrideProperty(serviceConfigProperty);
+      expect(serviceConfigProperty.get("overrides")[0]).to.eql(newSCP);
+    });
+  });
+
+  describe("#showComponentsShouldBeRestarted", function () {
+
+    var tests = [
+      {
+        input: {
+          'publicHostName1': ['TaskTracker'],
+          'publicHostName2': ['JobTracker', 'TaskTracker']
+        },
+        components: "2 TaskTrackers, 1 JobTracker",
+        text: Em.I18n.t('service.service.config.restartService.shouldBeRestarted').format(Em.I18n.t('common.components'))
+      },
+      {
+        input: {
+          'publicHostName1': ['TaskTracker']
+        },
+        components: "1 TaskTracker",
+        text: Em.I18n.t('service.service.config.restartService.shouldBeRestarted').format(Em.I18n.t('common.component'))
+      }
+    ];
+
+    beforeEach(function () {
+      sinon.stub(mainServiceInfoConfigsController, "showItemsShouldBeRestarted", Em.K);
+      mainServiceInfoConfigsController.set("content", {restartRequiredHostsAndComponents: ""});
+    });
+    afterEach(function () {
+      mainServiceInfoConfigsController.showItemsShouldBeRestarted.restore();
+      mainServiceInfoConfigsController.set("content", undefined);
+    });
+
+    tests.forEach(function (t) {
+      it("trigger showItemsShouldBeRestarted popup with components", function () {
+        mainServiceInfoConfigsController.set("content.restartRequiredHostsAndComponents", t.input);
+        mainServiceInfoConfigsController.showComponentsShouldBeRestarted();
+        expect(mainServiceInfoConfigsController.showItemsShouldBeRestarted.calledWith(t.components, t.text)).to.equal(true);
+      });
+    });
+  });
+
+  describe("#showHostsShouldBeRestarted", function () {
+
+    var tests = [
+      {
+        input: {
+          'publicHostName1': ['TaskTracker'],
+          'publicHostName2': ['JobTracker', 'TaskTracker']
+        },
+        hosts: "publicHostName1, publicHostName2",
+        text: Em.I18n.t('service.service.config.restartService.shouldBeRestarted').format(Em.I18n.t('common.hosts'))
+      },
+      {
+        input: {
+          'publicHostName1': ['TaskTracker']
+        },
+        hosts: "publicHostName1",
+        text: Em.I18n.t('service.service.config.restartService.shouldBeRestarted').format(Em.I18n.t('common.host'))
+      }
+    ];
+
+    beforeEach(function () {
+      sinon.stub(mainServiceInfoConfigsController, "showItemsShouldBeRestarted", Em.K);
+      mainServiceInfoConfigsController.set("content", {restartRequiredHostsAndComponents: ""});
+    });
+    afterEach(function () {
+      mainServiceInfoConfigsController.showItemsShouldBeRestarted.restore();
+      mainServiceInfoConfigsController.set("content", undefined);
+    });
+
+    tests.forEach(function (t) {
+      it("trigger showItemsShouldBeRestarted popup with hosts", function () {
+        mainServiceInfoConfigsController.set("content.restartRequiredHostsAndComponents", t.input);
+        mainServiceInfoConfigsController.showHostsShouldBeRestarted();
+        expect(mainServiceInfoConfigsController.showItemsShouldBeRestarted.calledWith(t.hosts, t.text)).to.equal(true);
+      });
+    });
+  });
+
+  describe("rollingRestartStaleConfigSlaveComponents", function () {
+    var tests = [
+      {
+        componentName: {
+          context: "ComponentName"
+        },
+        displayName: "displayName",
+        passiveState: "ON"
+      },
+      {
+        componentName: {
+          context: "ComponentName1"
+        },
+        displayName: "displayName1",
+        passiveState: "OFF"
+      }
+    ];
+
+    beforeEach(function () {
+      mainServiceInfoConfigsController.set("content", {displayName: "", passiveState: ""});
+      sinon.stub(batchUtils, "launchHostComponentRollingRestart", Em.K);
+    });
+    afterEach(function () {
+      batchUtils.launchHostComponentRollingRestart.restore();
+    });
+    tests.forEach(function (t) {
+      it("trigger rollingRestartStaleConfigSlaveComponents", function () {
+        mainServiceInfoConfigsController.set("content.displayName", t.displayName);
+        mainServiceInfoConfigsController.set("content.passiveState", t.passiveState);
+        mainServiceInfoConfigsController.rollingRestartStaleConfigSlaveComponents(t.componentName);
+        expect(batchUtils.launchHostComponentRollingRestart.calledWith(t.componentName.context, t.displayName, t.passiveState == "ON", true)).to.equal(true);
+      });
+    });
+  });
+
+  describe("#restartAllStaleConfigComponents", function () {
+    beforeEach(function () {
+      sinon.stub(batchUtils, "restartAllServiceHostComponents", Em.K);
+    });
+    afterEach(function () {
+      batchUtils.restartAllServiceHostComponents.restore();
+    });
+    it("trigger restartAllServiceHostComponents", function () {
+      mainServiceInfoConfigsController.restartAllStaleConfigComponents().onPrimary();
+      expect(batchUtils.restartAllServiceHostComponents.calledOnce).to.equal(true);
+    });
+  });
+
+  describe("#doCancel", function () {
+    beforeEach(function () {
+      sinon.stub(mainServiceInfoConfigsController, "loadStep", Em.K);
+    });
+    afterEach(function () {
+      mainServiceInfoConfigsController.loadStep.restore();
+    });
+    it("trigger loadStep", function () {
+      mainServiceInfoConfigsController.doCancel();
+      expect(mainServiceInfoConfigsController.loadStep.calledOnce).to.equal(true);
+    });
+  });
+
+  describe("#getCurrentServiceComponents", function () {
+    var t = Em.Object.create({
+      content: Em.Object.create({
+        hostComponents: [
+          Em.Object.create({
+            componentName: "componentName1",
+            displayName: "displayName1"
+          }),
+          Em.Object.create({
+            componentName: "componentName2",
+            displayName: "displayName2"
+          })
+        ]
+      }),
+      validComponents: Em.A([
+        Em.Object.create({
+          componentName: "componentName1",
+          displayName: "displayName1",
+          selected: false
+        }),
+        Em.Object.create({
+          componentName: "componentName2",
+          displayName: "displayName2",
+          selected: false
+        })
+      ])
+    });
+
+    beforeEach(function () {
+      mainServiceInfoConfigsController.set("content", { hostComponents: Em.A([])});
+    });
+
+    it("get current service components", function () {
+      mainServiceInfoConfigsController.get("content.hostComponents").push(t.content.hostComponents[0]);
+      var com = mainServiceInfoConfigsController.get("getCurrentServiceComponents");
+      expect(com[0]).to.eql(t.validComponents[0]);
+    });
+  });
+
+  describe("#getMasterComponentHostValue", function () {
+    var t = Em.Object.create({
+      content: Em.Object.create({
+        hostComponents: [
+          Em.Object.create({
+            componentName: "componentName2",
+            displayName: "displayName2",
+            host: Em.Object.create({
+              hostName: "hostName"
+            })
+          })
+        ]
+      })
+    });
+    beforeEach(function () {
+      mainServiceInfoConfigsController.set("content", { hostComponents: Em.A([])});
+    });
+
+    it("returns hostname", function () {
+      mainServiceInfoConfigsController.get("content.hostComponents").push(t.content.hostComponents[0]);
+      expect(mainServiceInfoConfigsController.getMasterComponentHostValue(t.content.hostComponents[0].componentName)).to.equal(t.content.hostComponents[0].host.hostName);
+    });
+  });
+
+  describe("#setServerConfigValue", function () {
+
+    it("parsing storm.zookeeper.servers property in non standart method", function () {
+      expect(mainServiceInfoConfigsController.setServerConfigValue("storm.zookeeper.servers", ["a", "b"])).to.equal('[\'a\',\'b\']');
+    });
+    it("parsing content property in non standart method", function () {
+      expect(mainServiceInfoConfigsController.setServerConfigValue("content", "value")).to.equal("value");
+    });
+    it("parsing default properties", function () {
+      expect(mainServiceInfoConfigsController.setServerConfigValue("any.other.property", "value&lt;")).to.equal("value<");
+    });
+  });
+
+  describe("#createSiteObj", function () {
+
+    var tests = [
+      {
+        siteName: "hdfs-site",
+        tagName: "version1",
+        siteObj: Em.A([
+          {
+            name: "property1",
+            value: "value1"
+          },
+          {
+            name: "property2",
+            value: "value2&lt;"
+          }
+        ]),
+        result: {
+          "type": "hdfs-site",
+          "tag": "version1",
+          "properties": {
+            "property1": "value1",
+            "property2": "value2<"
+          }
+        },
+        m: "default"
+      },
+      {
+        siteName: "falcon-startup.properties",
+        tagName: "version1",
+        siteObj: Em.A([
+          {
+            name: "property1",
+            value: "value1"
+          },
+          {
+            name: "property2",
+            value: "value2&lt;"
+          }
+        ]),
+        result: {
+          "type": "falcon-startup.properties",
+          "tag": "version1",
+          "properties": {
+            "property1": "value1",
+            "property2": "value2&lt;"
+          }
+        },
+        m: "for falcon-startup.properties"
+
+      }
+    ];
+    tests.forEach(function (t) {
+      it("create site object " + t.m, function () {
+        expect(mainServiceInfoConfigsController.createSiteObj(t.siteName, t.tagName, t.siteObj)).to.deep.eql(t.result)
+      });
+    });
+  });
+
+  describe("#createCoreSiteObj", function () {
+
+    var tests = [
+      {
+        tagName: "version1",
+        uiConfigs: Em.A([
+          Em.Object.create({
+            name: "property1",
+            value: "value1",
+            filename: "core-site.xml"
+          }),
+          Em.Object.create({
+            name: "property2",
+            value: "value2&lt;",
+            filename: "core-site.xml"
+          })
+        ]),
+        result: {
+          "type": "core-site",
+          "tag": "version1",
+          "properties": {
+            "property1": "value1",
+            "property2": "value2<"
+          }
+        }
+      }
+    ];
+    tests.forEach(function (t) {
+      it("create core object", function () {
+        mainServiceInfoConfigsController.set("uiConfigs", t.uiConfigs);
+        expect(mainServiceInfoConfigsController.createCoreSiteObj(t.tagName)).to.deep.eql(t.result);
+      });
+    });
+  });
+
+  describe("#createGlobalSiteObj", function () {
+
+    var t = {
+      tagName: "version1",
+      globalConfigs: Em.A([
+        Em.Object.create({
+          name: "property1",
+          value: "value1"
+        }),
+        Em.Object.create({
+          name: "property2",
+          value: "value2&lt;"
+        }),
+        Em.Object.create({
+          name: "some_heapsize",
+          value: "1000"
+        }),
+        Em.Object.create({
+          name: "some_newsize",
+          value: "1000"
+        }),
+        Em.Object.create({
+          name: "some_maxnewsize",
+          value: "1000"
+        }),
+        Em.Object.create({
+          name: "hadoop_heapsize",
+          value: "1000"
+        })
+      ]),
+      result: {
+        "type": "global",
+        "tag": "version1",
+        "properties": {
+          "property1": "value1",
+          "property2": "value2<",
+          "some_heapsize": "1000m",
+          "some_newsize": "1000m",
+          "some_maxnewsize": "1000m",
+          "hadoop_heapsize": "1000"
+        }
+      }
+    };
+    it("create global object", function () {
+      expect(mainServiceInfoConfigsController.createGlobalSiteObj(t.tagName, t.globalConfigs)).to.deep.eql(t.result);
+    });
+  });
+
+  describe("#doPUTClusterConfigurationSiteErrorCallback", function () {
+    it("set doPUTClusterConfigurationSiteResult to false", function () {
+      mainServiceInfoConfigsController.doPUTClusterConfigurationSiteErrorCallback({responseText: ""});
+      expect(mainServiceInfoConfigsController.get("doPUTClusterConfigurationSiteResult")).to.equal(false);
+    });
+  });
+
+  describe("#doPUTClusterConfigurationSiteSuccessCallback", function () {
+    it("set doPUTClusterConfigurationSiteResult to true", function () {
+      mainServiceInfoConfigsController.doPUTClusterConfigurationSiteSuccessCallback();
+      expect(mainServiceInfoConfigsController.get("doPUTClusterConfigurationSiteResult")).to.equal(true);
+    });
+  });
+
+  describe("#doPUTClusterConfigurationSite", function () {
+    var t = {
+      data: "data",
+      request: {
+        Clusters: {
+          desired_config: "data"
+        }
+      }
+    };
+    var temp = App.router.getClusterName;
+    beforeEach(function () {
+      App.router.getClusterName = function () {
+        return "clName";
+      };
+      sinon.spy($, "ajax");
+    });
+    afterEach(function () {
+      $.ajax.restore();
+      App.router.getClusterName = temp;
+    });
+    it("ajax request to put clsuter cfg", function () {
+      expect(mainServiceInfoConfigsController.doPUTClusterConfigurationSite(t.data)).to.equal(mainServiceInfoConfigsController.get("doPUTClusterConfigurationSiteResult"));
+      expect(JSON.parse($.ajax.args[0][0].data)).to.deep.equal(t.request);
+    });
+  });
+
+  describe("#isConfigChanged", function () {
+
+    var tests = [
+      {
+        loadedConfig: {
+          apptimelineserver_heapsize: "1024",
+          hbase_log_dir: "/var/log/hbase",
+          lzo_enabled: "true"
+        },
+        savingConfig: {
+          apptimelineserver_heapsize: "1024",
+          hbase_log_dir: "/var/log/hbase",
+          lzo_enabled: "true"
+        },
+        m: "configs doesn't changed",
+        res: false
+      },
+      {
+        loadedConfig: {
+          apptimelineserver_heapsize: "1024",
+          hbase_log_dir: "/var/log/hbase",
+          lzo_enabled: "true"
+        },
+        savingConfig: {
+          apptimelineserver_heapsize: "1024",
+          hbase_log_dir: "/var/log/hbase",
+          lzo_enabled: "false"
+        },
+        m: "configs changed",
+        res: true
+      },
+      {
+        loadedConfig: {
+          apptimelineserver_heapsize: "1024",
+          hbase_log_dir: "/var/log/hbase"
+        },
+        savingConfig: {
+          apptimelineserver_heapsize: "1024",
+          hbase_log_dir: "/var/log/hbase",
+          lzo_enabled: "false"
+        },
+        m: "add new config",
+        res: true
+      }
+    ];
+
+    tests.forEach(function(t){
+      it(t.m, function () {
+        expect(mainServiceInfoConfigsController.isConfigChanged(t.loadedConfig, t.savingConfig)).to.equal(t.res);
+      });
+    });
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/68020574/ambari-web/test/controllers/main/service/item_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/service/item_test.js b/ambari-web/test/controllers/main/service/item_test.js
new file mode 100644
index 0000000..f7b43ed
--- /dev/null
+++ b/ambari-web/test/controllers/main/service/item_test.js
@@ -0,0 +1,708 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+App = require('app');
+require('ember');
+require('models/host_component')
+require('views/common/modal_popup');
+require('mixins/common/userPref');
+require('controllers/application');
+require('controllers/global/background_operations_controller');
+require('controllers/global/cluster_controller');
+require('controllers/main/service/reassign_controller')
+require('controllers/main/service/item');
+var batchUtils = require('utils/batch_scheduled_requests');
+
+describe('App.MainServiceItemController', function () {
+
+  describe('#setStartStopState', function () {
+    var tests = [
+      {
+        serviceController: {
+          serviceName: "YARN"
+        },
+        backgroundOperationsController: {
+          services: [
+            {
+              isRunning: true,
+              dependentService: "ALL_SERVICES"
+            }
+          ]
+        },
+        isPending: true,
+        m: 'operaion is active because all services are running'
+      },
+      {
+        serviceController: {
+          serviceName: "HBASE"
+        },
+        backgroundOperationsController: {
+          services: [
+            {
+              isRunning: true,
+              dependentService: "HBASE"
+            }
+          ]
+        },
+        isPending: true,
+        m: 'operaion is active button because current service is running'
+      },
+      {
+        serviceController: {
+          serviceName: "HDFS"
+        },
+        backgroundOperationsController: {
+          services: [
+
+          ]
+        },
+        isPending: true,
+        m: 'pending is true - backgroundOperationsController.services is empty'
+      },
+      {
+        serviceController: {
+          serviceName: "HBASE"
+        },
+        backgroundOperationsController: {
+          services: [
+            {
+              isRunning: false,
+              dependentService: "ALL_SERVICES"
+            }
+          ]
+        },
+        isPending: false,
+        m: 'pending is false - operation is not running'
+      },
+      {
+        serviceController: {
+          serviceName: "HBASE"
+        },
+        backgroundOperationsController: {
+          services: [
+            {
+              isRunning: true,
+              dependentService: "HDFS"
+            }
+          ]
+        },
+        isPending: false,
+        m: 'pending is false - current service is not running'
+      }
+    ];
+
+
+    tests.forEach(function (test) {
+      it(test.m, function () {
+        var backgroundOperationsController = App.BackgroundOperationsController.create();
+        backgroundOperationsController.set('services', []);
+        test.backgroundOperationsController.services.forEach(function (service) {
+          backgroundOperationsController.get('services').push(service);
+        });
+        backgroundOperationsController.set("serviceTimestamp", new Date().getTime());
+        App.router.set('backgroundOperationsController', backgroundOperationsController);
+        var mainServiceItemController = App.MainServiceItemController.create({content: {serviceName: test.serviceController.serviceName}});
+        mainServiceItemController.setStartStopState();
+        expect(mainServiceItemController.get('isPending')).to.equal(test.isPending);
+      });
+    })
+  });
+
+  describe('#reassignMaster()', function () {
+    var v;
+    var tests = [
+      {
+        host_components: [
+          {component_name: "RESOURCEMANGER"}
+        ],
+        conponentName: "RESOURCEMANGER",
+        result: true,
+        m: 'run reassignMaster'
+      },
+      {
+        host_components: [
+          {component_name: "RESOURCEMANGER"}
+        ],
+        conponentName: "DATANODE",
+        result: false,
+        m: 'don\t run reassignMaster'
+      }
+    ];
+
+    tests.forEach(function (test) {
+      var reassignMasterController = App.ReassignMasterController.create({currentStep: ''});
+      beforeEach(function () {
+        sinon.spy(reassignMasterController, 'saveComponentToReassign');
+        sinon.spy(reassignMasterController, 'getSecurityStatus');
+        sinon.spy(reassignMasterController, 'setCurrentStep');
+        App.router.transitionTo = Em.K;
+      });
+      afterEach(function () {
+        reassignMasterController.saveComponentToReassign.restore();
+        reassignMasterController.getSecurityStatus.restore();
+        reassignMasterController.setCurrentStep.restore();
+        App.router.transitionTo = v;
+      });
+      it(test.m, function () {
+        v = App.router.transitionTo;
+        var mainServiceItemController = App.MainServiceItemController.create({});
+        App.router.set('reassignMasterController', reassignMasterController);
+        App.store.loadMany(App.HostComponent, test.host_components);
+        mainServiceItemController.reassignMaster(test.conponentName);
+        expect(reassignMasterController.saveComponentToReassign.calledOnce).to.equal(test.result);
+        expect(reassignMasterController.getSecurityStatus.calledOnce).to.equal(test.result);
+        expect(reassignMasterController.setCurrentStep.calledOnce).to.equal(test.result);
+      });
+    }, this);
+  });
+
+  describe("#updateService", function () {
+
+    var tests = [
+      {
+        params: {
+          passive_state: "ON"
+        },
+        m: "turn on passive"
+      },
+      {
+        params: {
+          passive_state: "OFF"
+        },
+        m: "turn off passive"
+      }
+    ];
+    tests.forEach(function (test) {
+      it(test.m, function () {
+        var clusterController = App.ClusterController.create();
+        App.router.set('clusterController', clusterController);
+        var mainServiceItemController = App.MainServiceItemController.create({content: {passiveState: "ON"}});
+        mainServiceItemController.updateService(null, null, test.params);
+        expect(mainServiceItemController.get('content.passiveState')).to.equal(test.params.passive_state);
+      });
+    });
+  });
+
+  describe("#doAction", function () {
+
+    var el = document.createElement("BUTTON");
+    el.disabled = false;
+    var tests = [
+      {
+        event: {
+          target: el,
+          context: {
+            action: 'runSmokeTest'
+          }
+        },
+        m: "run runSmokeTest"
+      },
+      {
+        event: {
+          target: el,
+          context: {
+            action: 'refreshConfigs'
+          }
+        },
+        m: "run refreshConfigs"
+      },
+      {
+        event: {
+          target: el,
+          context: {
+            action: 'restartAllHostComponents'
+          }
+        },
+        m: "run restartAllHostComponents"
+      },
+      {
+        event: {
+          target: el,
+          context: {
+            action: 'rollingRestart'
+          }
+        },
+        m: "run rollingRestart"
+      }
+    ];
+
+    tests.forEach(function (test) {
+      var mainServiceItemController = App.MainServiceItemController.create({});
+      mainServiceItemController.set(test.event.context.action, Em.K);
+      beforeEach(function () {
+        sinon.spy(mainServiceItemController, test.event.context.action);
+      });
+      afterEach(function () {
+        mainServiceItemController[test.event.context.action].restore();
+      });
+      it(test.m, function () {
+        mainServiceItemController.doAction(test.event);
+        expect(mainServiceItemController[test.event.context.action].calledOnce).to.equal(!test.event.target.disabled);
+      });
+    });
+  });
+
+  describe("#startStopPopupPrimary", function () {
+
+
+    var tests = [
+      {
+        data: {
+          "serviceName": "HDFS",
+          "state": "STARTED",
+          "query": Em.Object.create({ServiceInfo: "FAIL"})
+        },
+        request: {
+          "RequestInfo": {
+            "context": "_PARSE_.START.HDFS"
+          },
+          "Body": {
+            "ServiceInfo": {
+              "state": "STARTED"
+            }
+          }
+        },
+        m: "Start HDFS"
+      },
+      {
+        data: {
+          "serviceName": "YARN",
+          "state": "STOPPED",
+          "query": Em.Object.create({ServiceInfo: "FAIL"})
+        },
+        request: {
+          "RequestInfo": {
+            "context": "_PARSE_.STOP.YARN"
+          },
+          "Body": {
+            "ServiceInfo": {
+              "state": "STOPPED"
+            }
+          }
+        },
+        m: "Stop YARN"
+      }
+    ];
+
+    beforeEach(function () {
+      sinon.spy($, 'ajax');
+    });
+
+    afterEach(function () {
+      $.ajax.restore();
+    });
+
+
+    tests.forEach(function (test) {
+      it('', function () {
+        var mainServiceItemController = App.MainServiceItemController.create({content: {serviceName: test.data.serviceName}});
+        mainServiceItemController.startStopPopupPrimary(test.data.state, test.data.query);
+        expect($.ajax.calledOnce).to.equal(true);
+
+        expect(JSON.parse($.ajax.args[0][0].data).Body.ServiceInfo.state).to.equal(test.request.Body.ServiceInfo.state);
+        expect(JSON.parse($.ajax.args[0][0].data).RequestInfo.context).to.equal(test.request.RequestInfo.context);
+
+        expect(mainServiceItemController.get('isStopDisabled')).to.equal(true);
+        expect(mainServiceItemController.get('isStartDisabled')).to.equal(true);
+      });
+    });
+
+
+  });
+
+  describe("#startStopPopupSuccessCallback", function () {
+
+    var data = {
+      Requests: true
+    };
+    var params = Em.Object.create({
+      query: Em.Object.create()
+    });
+    var ajaxOptions = {
+      data: '{"RequestInfo":{"context":"_PARSE_.STOP.ZOOKEEPER"},"Body":{"ServiceInfo":{"state":"INSTALLED"}}}'
+    };
+
+    var content = {
+      workStatus: "",
+      hostComponents: [
+        {
+          workStatus: ""
+        }
+      ]
+    };
+
+    var mainServiceItemController = App.MainServiceItemController.create({content: content});
+    var applicationController = App.ApplicationController.create(App.UserPref, {});
+    var clusterController = App.ClusterController.create({loadUpdatedStatusDelayed: Em.K});
+    var backgroundOperationsController = App.BackgroundOperationsController.create({showPopup: Em.K});
+    App.testMode = false;
+    beforeEach(function () {
+      App.testMode = false;
+      sinon.spy(clusterController, "loadUpdatedStatusDelayed");
+    });
+    afterEach(function () {
+      clusterController.loadUpdatedStatusDelayed.restore();
+      App.testMode = true;
+    });
+    it("open bgo popup", function () {
+      App.router.set('applicationController', applicationController);
+      App.router.set('clusterController', clusterController);
+      App.router.set('backgroundOperationsController', backgroundOperationsController);
+      mainServiceItemController.startStopPopupSuccessCallback(data, ajaxOptions, params);
+      expect(clusterController.loadUpdatedStatusDelayed.calledOnce).to.equal(true);
+    })
+  });
+
+
+  describe("#startService , #stopService", function () {
+    var mainServiceItemController = App.MainServiceItemController.create({startStopPopup: Em.K});
+    beforeEach(function () {
+      sinon.spy(mainServiceItemController, "startStopPopup");
+    });
+    afterEach(function () {
+      mainServiceItemController.startStopPopup.restore();
+    });
+    it("start service", function () {
+      mainServiceItemController.startService({});
+      expect(mainServiceItemController.startStopPopup.calledWith({},App.HostComponentStatus.started)).to.equal(true);
+    });
+    it("stop service", function () {
+      mainServiceItemController.stopService({});
+      expect(mainServiceItemController.startStopPopup.calledWith({},App.HostComponentStatus.stopped)).to.equal(true);
+    });
+  });
+
+
+  describe("#turnOnOffPassive", function () {
+    var mainServiceItemController = App.MainServiceItemController.create({turnOnOffPassiveRequest: Em.K});
+    beforeEach(function () {
+      sinon.spy(mainServiceItemController, "turnOnOffPassiveRequest");
+    });
+    afterEach(function () {
+      mainServiceItemController.turnOnOffPassiveRequest.restore();
+    });
+    it("turns on/off passive mode for service", function () {
+      mainServiceItemController.turnOnOffPassive({}).onPrimary();
+      expect(mainServiceItemController.turnOnOffPassiveRequest.calledOnce).to.equal(true);
+    });
+  });
+
+  describe("#runSmokeTest", function () {
+    var tests = [
+      {
+        content: {
+          id: "YARN",
+          service_name: "YARN",
+          work_status: "STARTED"
+        },
+        startSmoke: true,
+        serviceName: "MAPREDUCE2",
+        m: "don't run smoke test primary for MAPREDUCE2"
+      },
+      {
+        content: {
+          id: "YARN",
+          service_name: "YARN",
+          work_status: "STOPPED"
+        },
+        startSmoke: false,
+        serviceName: "MAPREDUCE2",
+        m: "run smoke test primary for MAPREDUCE2"
+      },
+      {
+        m: "run smoke test primary for all services (not MAPREDUCE2)",
+        startSmoke: true,
+        default: true
+      }
+    ];
+
+    tests.forEach(function (test) {
+      var mainServiceItemController = test.default ? App.MainServiceItemController.create({runSmokeTestPrimary: Em.K}) :
+          App.MainServiceItemController.create({content: {serviceName: test.serviceName}, runSmokeTestPrimary: Em.K});
+      beforeEach(function () {
+        sinon.spy(mainServiceItemController, "runSmokeTestPrimary");
+      });
+      afterEach(function () {
+        mainServiceItemController.runSmokeTestPrimary.restore();
+      });
+      it(test.m, function () {
+        if (!test.default) {
+          App.store.load(App.Service, test.content);
+        }
+        mainServiceItemController.runSmokeTest({}).onPrimary();
+        expect(mainServiceItemController.runSmokeTestPrimary.calledOnce).to.equal(test.startSmoke);
+      });
+    });
+  });
+
+  describe("#refreshConfigs", function () {
+    var temp = batchUtils.restartHostComponents;
+    beforeEach(function () {
+      batchUtils.restartHostComponents = Em.K;
+      sinon.spy(batchUtils, "restartHostComponents");
+    });
+    afterEach(function () {
+      batchUtils.restartHostComponents.restore();
+      batchUtils.restartHostComponents = temp;
+    });
+    var tests = [
+      {
+        isClientsOnly: true,
+        m: "run refresh for clients"
+      },
+      {
+        isClientsOnly: false,
+        m: "don't run refresh for non clients"
+      }
+    ];
+    tests.forEach(function (test) {
+      var mainServiceItemController = App.MainServiceItemController.create({content: {isClientsOnly: test.isClientsOnly}});
+      it(test.m, function () {
+        if (test.isClientsOnly) {
+          mainServiceItemController.refreshConfigs().onPrimary();
+        } else {
+          mainServiceItemController.refreshConfigs();
+        }
+        expect(batchUtils.restartHostComponents.calledOnce).to.equal(test.isClientsOnly);
+      });
+    }, this);
+  });
+
+  describe("#startStopPopup", function () {
+    var el = document.createElement("BUTTON");
+    el.disabled = false;
+    var event = {
+      target: el
+    }
+    var mainServiceItemController = App.MainServiceItemController.create({content: {serviceName: "HDFS"}});
+    beforeEach(function () {
+      sinon.spy(mainServiceItemController, "startStopPopupPrimary");
+    });
+    afterEach(function () {
+      mainServiceItemController.startStopPopupPrimary.restore();
+    });
+    it("start start/stop service popup", function () {
+      mainServiceItemController.startStopPopup(event, "").onPrimary();
+      expect(mainServiceItemController.startStopPopupPrimary.calledOnce).to.equal(true);
+    });
+  });
+
+  describe("#restartAllHostComponents", function () {
+    var temp = batchUtils.restartAllServiceHostComponents;
+    beforeEach(function () {
+      batchUtils.restartAllServiceHostComponents = Em.K;
+      sinon.spy(batchUtils, "restartAllServiceHostComponents");
+    });
+    afterEach(function () {
+      batchUtils.restartAllServiceHostComponents.restore();
+      batchUtils.restartAllServiceHostComponents = temp;
+    });
+
+    var mainServiceItemController = App.MainServiceItemController.create({content: {displayName: "HDFS"}});
+
+    it("start restartAllHostComponents for service", function () {
+      mainServiceItemController.restartAllHostComponents({}).onPrimary();
+      expect(batchUtils.restartAllServiceHostComponents.calledOnce).to.equal(true);
+    });
+  });
+
+  describe("#rollingRestart", function () {
+    var temp = batchUtils.launchHostComponentRollingRestart;
+    beforeEach(function () {
+      batchUtils.launchHostComponentRollingRestart = Em.K;
+      sinon.spy(batchUtils, "launchHostComponentRollingRestart");
+    });
+    afterEach(function () {
+      batchUtils.launchHostComponentRollingRestart.restore();
+      batchUtils.launchHostComponentRollingRestart = temp;
+    });
+
+    var mainServiceItemController = App.MainServiceItemController.create();
+
+    it("start restartAllHostComponents for service", function () {
+      mainServiceItemController.rollingRestart();
+      expect(batchUtils.launchHostComponentRollingRestart.calledOnce).to.equal(true);
+    });
+  });
+
+  describe("#isStartDisabled", function () {
+    var tests = [
+      {
+        content: {
+          healthStatus: 'red'
+        },
+        isPending: true,
+        disabled: true,
+        m: "disabled because of pending"
+      },
+      {
+        content: {
+          healthStatus: 'green'
+        },
+        isPending: false,
+        disabled: true,
+        m: "disabled because healthStatus is not red"
+      },
+      {
+        content: {
+          healthStatus: 'red'
+        },
+        isPending: false,
+        disabled: false,
+        m: "enabled because healthStatus is red and pending is false"
+      }
+    ];
+    tests.forEach(function (test) {
+      it(test.m, function () {
+        var mainServiceItemController = App.MainServiceItemController.create({content: {healthStatus: test.content.healthStatus}, isPending: test.isPending});
+        expect(mainServiceItemController.get('isStartDisabled')).to.equal(test.disabled);
+      });
+    });
+  });
+
+  describe("#isSopDisabled", function () {
+    var tests = [
+      {
+        content: {
+          healthStatus: 'red'
+        },
+        isPending: true,
+        disabled: true,
+        m: "disabled because of pending"
+      },
+      {
+        content: {
+          healthStatus: 'green'
+        },
+        isPending: false,
+        disabled: false,
+        m: "enabled because healthStatus is green and pending is false"
+      },
+      {
+        content: {
+          healthStatus: 'red'
+        },
+        isPending: false,
+        disabled: true,
+        m: "disabled because healthStatus is not green"
+      }
+    ];
+    tests.forEach(function (test) {
+      it(test.m, function () {
+        var mainServiceItemController = App.MainServiceItemController.create({content: test.content, isPending: test.isPending});
+        expect(mainServiceItemController.get('isStopDisabled')).to.equal(test.disabled);
+      });
+    });
+  });
+
+  describe("#runRebalancer", function () {
+    it("run rebalancer", function () {
+      var mainServiceItemController = App.MainServiceItemController.create({content: {runRebalancer: false}});
+      mainServiceItemController.runRebalancer().onPrimary();
+      expect(mainServiceItemController.get("content.runRebalancer")).to.equal(true);
+    });
+  });
+
+  describe("#runCompaction", function () {
+    it("run compaction", function () {
+      var mainServiceItemController = App.MainServiceItemController.create({content: {runCompaction: false}});
+      mainServiceItemController.runCompaction().onPrimary();
+      expect(mainServiceItemController.get("content.runCompaction")).to.equal(true);
+    });
+  });
+
+  describe("#turnOnOffPassiveRequest", function () {
+    var tests = [
+      {
+        data: {
+          "requestInfo": 'Turn On Maintenance Mode',
+          "serviceName" : "HDFS",
+          "passive_state": "ON"
+        },
+        RequestInfo: {
+          "context": 'Turn On Maintenance Mode'
+        },
+        Body: {
+          ServiceInfo: {
+            maintenance_state: "ON"
+          }
+        }
+      }
+    ];
+
+    beforeEach(function () {
+      sinon.spy($, 'ajax');
+    });
+
+    afterEach(function () {
+      $.ajax.restore();
+    });
+
+    tests.forEach(function (test) {
+      it('send request to turn on passive state', function () {
+        var mainServiceItemController = App.MainServiceItemController.create({content: {serviceName: test.data.serviceName}});
+        mainServiceItemController.turnOnOffPassiveRequest(test.data.passive_state, test.data.requestInfo);
+        expect($.ajax.calledOnce).to.equal(true);
+
+        expect(JSON.parse($.ajax.args[0][0].data).Body.ServiceInfo.maintenance_state).to.equal(test.Body.ServiceInfo.maintenance_state);
+        expect(JSON.parse($.ajax.args[0][0].data).RequestInfo.context).to.equal(test.RequestInfo.context);
+      });
+    });
+  });
+
+  describe("#runSmokeTestPrimary", function () {
+    var tests = [
+      {
+        data: {
+          'serviceName': "HDFS",
+          'displayName': "HDFS",
+          'query': "test"
+        },
+        "RequestInfo": {
+          "context": "HDFS Service Check",
+          "command" : "HDFS_SERVICE_CHECK"
+        },
+        "Requests/resource_filters": [{"service_name" : "HDFS"}]
+      }
+    ];
+    tests.forEach(function (test) {
+
+    var mainServiceItemController = App.MainServiceItemController.create({content: {serviceName: test.data.serviceName,
+      displayName: test.data.displayName}});
+    beforeEach(function () {
+      mainServiceItemController.set("runSmokeTestErrorCallBack", Em.K);
+      mainServiceItemController.set("runSmokeTestSuccessCallBack", Em.K);
+      sinon.spy($, 'ajax');
+    });
+
+    afterEach(function () {
+      $.ajax.restore();
+    });
+
+      it('send request to run smoke test', function () {
+
+        mainServiceItemController.runSmokeTestPrimary(test.data.query);
+        expect($.ajax.calledOnce).to.equal(true);
+
+        expect(JSON.parse($.ajax.args[0][0].data).RequestInfo.context).to.equal(test.RequestInfo.context);
+        expect(JSON.parse($.ajax.args[0][0].data).RequestInfo.command).to.equal(test.RequestInfo.command);
+        expect(JSON.parse($.ajax.args[0][0].data)["Requests/resource_filters"][0].serviceName).to.equal(test["Requests/resource_filters"][0].serviceName);
+      });
+    });
+  });
+});