You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by at...@apache.org on 2016/02/26 11:35:04 UTC

ambari git commit: AMBARI-15185 Cover main controllers with unit tests. (atkach)

Repository: ambari
Updated Branches:
  refs/heads/trunk 6e758b76a -> 6a808b19f


AMBARI-15185 Cover main controllers with unit tests. (atkach)


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

Branch: refs/heads/trunk
Commit: 6a808b19f1ae5a368ffac30709e8182df5513cc4
Parents: 6e758b7
Author: Andrii Tkach <at...@hortonworks.com>
Authored: Thu Feb 25 19:11:48 2016 +0200
Committer: Andrii Tkach <at...@hortonworks.com>
Committed: Fri Feb 26 12:33:53 2016 +0200

----------------------------------------------------------------------
 ambari-web/app/assets/test/tests.js             |   2 +
 ambari-web/app/controllers/main/host.js         |  32 +-
 ambari-web/app/controllers/main/service.js      |  10 +-
 .../app/controllers/main/views_controller.js    |  23 +-
 .../resourceManager/wizard_view.js              |  14 +-
 .../main/alert_definitions_controller_test.js   |  19 +
 ambari-web/test/controllers/main/host_test.js   | 400 +++++++++++++++++--
 .../test/controllers/main/service_test.js       | 303 ++++++++++++++
 .../controllers/main/views_controller_test.js   | 102 +++++
 .../resourceManager/step3_view_test.js          |  49 +++
 .../resourceManager/wizard_view_test.js         | 137 +++++++
 11 files changed, 1031 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/6a808b19/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 4edcc5e..1954432 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -282,6 +282,8 @@ var files = [
   'test/views/main/admin/highAvailability/nameNode/step4_view_test',
   'test/views/main/admin/highAvailability/nameNode/step6_view_test',
   'test/views/main/admin/highAvailability/nameNode/step8_view_test',
+  'test/views/main/admin/highAvailability/resourceManager/step3_view_test',
+  'test/views/main/admin/highAvailability/resourceManager/wizard_view_test',
   'test/views/main/admin/highAvailability/nameNode/wizard_view_test',
   'test/views/main/admin/highAvailability/progress_view_test',
   'test/views/common/host_progress_popup_body_view_test',

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a808b19/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 f1a3afb..dac005b 100644
--- a/ambari-web/app/controllers/main/host.js
+++ b/ambari-web/app/controllers/main/host.js
@@ -25,13 +25,21 @@ App.MainHostController = Em.ArrayController.extend(App.TableServerMixin, {
   clearFilters: null,
 
   filteredCount: 0,
+
   /**
    * total number of installed hosts
+   * @type {number}
    */
   totalCount: function () {
     return this.get('hostsCountMap')['TOTAL'] || 0;
   }.property('hostsCountMap'),
+
+  /**
+   * @type {boolean}
+   * @default false
+   */
   resetStartIndex: false,
+
   /**
    * flag responsible for updating status counters of hosts
    */
@@ -341,9 +349,7 @@ App.MainHostController = Em.ArrayController.extend(App.TableServerMixin, {
   /**
    * success callback on <code>updateStatusCounters()</code>
    */
-  updateStatusCountersErrorCallback: function() {
-
-  },
+  updateStatusCountersErrorCallback: Em.K,
 
   /**
    * Return value without predicate
@@ -351,13 +357,13 @@ App.MainHostController = Em.ArrayController.extend(App.TableServerMixin, {
    * @return {String}
    */
   getProperValue: function (value) {
-    return (value.charAt(0) === '>' || value.charAt(0) === '<' || value.charAt(0) === '=') ? value.substr(1, value.length) : value;
+    return (['>', '<', '='].contains(value.charAt(0))) ? value.substr(1, value.length) : value;
   },
 
   /**
    * Return value converted to kilobytes
    * @param {String} value
-   * @return {*}
+   * @return {number}
    */
   convertMemory: function (value) {
     var scale = value.charAt(value.length - 1);
@@ -396,7 +402,7 @@ App.MainHostController = Em.ArrayController.extend(App.TableServerMixin, {
     value = this.getProperValue(value);
     var parsedValue = parseFloat(value);
     if (isNaN(parsedValue)) {
-      return value;
+      return [0, 0];
     }
     var parsedValuePair = this.rangeConvertNumber(parsedValue, scale);
     var multiplyingFactor = 1;
@@ -429,7 +435,7 @@ App.MainHostController = Em.ArrayController.extend(App.TableServerMixin, {
    */
   rangeConvertNumber: function (value, scale) {
     if (isNaN(value)) {
-      return value;
+      return [0, 0];
     }
     var valuePair = [];
     switch (scale) {
@@ -449,8 +455,8 @@ App.MainHostController = Em.ArrayController.extend(App.TableServerMixin, {
 
   /**
    * Return comparison type depending on populated predicate
-   * @param value
-   * @return {String}
+   * @param {string} value
+   * @return {string}
    */
   getComparisonType: function (value) {
     var comparisonChar = value.charAt(0);
@@ -473,8 +479,7 @@ App.MainHostController = Em.ArrayController.extend(App.TableServerMixin, {
    * @param {App.HostComponent} component
    */
   filterByComponent: function (component) {
-    if (!component)
-      return;
+    if (!component) return;
     var id = component.get('componentName');
     var column = 6;
 
@@ -492,8 +497,7 @@ App.MainHostController = Em.ArrayController.extend(App.TableServerMixin, {
    * @param {String} state
    */
   filterByStack: function (displayName, state) {
-    if (!displayName || !state)
-      return;
+    if (!displayName || !state) return;
     var column = 11;
 
     var filterForStack = {
@@ -525,7 +529,7 @@ App.MainHostController = Em.ArrayController.extend(App.TableServerMixin, {
    */
   removeHosts: function () {
     var hosts = this.get('content');
-    var selectedHosts = hosts.filterProperty('isChecked', true);
+    var selectedHosts = hosts.filterProperty('isChecked');
     this.get('fullContent').removeObjects(selectedHosts);
   },
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a808b19/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 ab68890..44b8b21 100644
--- a/ambari-web/app/controllers/main/service.js
+++ b/ambari-web/app/controllers/main/service.js
@@ -50,10 +50,10 @@ App.MainServiceController = Em.ArrayController.extend({
    * @type {bool}
    */
   isAllServicesInstalled: function () {
-    if (!this.get('content.content')) return false;
+    if (!this.get('content')) return false;
     var availableServices = App.StackService.find().mapProperty('serviceName');
-    return this.get('content.content').length == availableServices.length;
-  }.property('content.content.@each', 'content.content.length'),
+    return this.get('content').length == availableServices.length;
+  }.property('content.@each', 'content.length'),
 
   /**
    * Should "Start All"-button be disabled
@@ -192,7 +192,7 @@ App.MainServiceController = Em.ArrayController.extend({
   isStopAllServicesFailed: function() {
     var workStatuses = App.Service.find().mapProperty('workStatus');
     for (var i = 0; i < workStatuses.length; i++) {
-      if (workStatuses[i] != 'INSTALLED' && workStatuses[i] != 'STOPPING') {
+      if (workStatuses[i] !== 'INSTALLED' && workStatuses[i] !== 'STOPPING') {
         return true;
       }
     }
@@ -210,7 +210,7 @@ App.MainServiceController = Em.ArrayController.extend({
         App.router.get('backgroundOperationsController').showPopup();
       }
 
-      Ember.run.later(function () {
+      Em.run.later(function () {
         self.set('shouldStart', true);
       }, App.bgOperationsUpdateInterval);
     });

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a808b19/ambari-web/app/controllers/main/views_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/views_controller.js b/ambari-web/app/controllers/main/views_controller.js
index 06407c2..ed7cc23 100644
--- a/ambari-web/app/controllers/main/views_controller.js
+++ b/ambari-web/app/controllers/main/views_controller.js
@@ -19,7 +19,7 @@
 var App = require('app');
 
 App.MainViewsController = Em.Controller.extend({
-  name:'mainViewsController',
+  name: 'mainViewsController',
 
   isDataLoaded: false,
 
@@ -43,15 +43,14 @@ App.MainViewsController = Em.Controller.extend({
 
 
   loadAmbariViews: function () {
-    if (!App.router.get('loggedIn')) {
-      return;
+    if (App.router.get('loggedIn')) {
+      return App.ajax.send({
+        name: 'views.info',
+        sender: this,
+        success: 'loadAmbariViewsSuccess',
+        error: 'loadAmbariViewsError'
+      });
     }
-    App.ajax.send({
-      name: 'views.info',
-      sender: this,
-      success: 'loadAmbariViewsSuccess',
-      error: 'loadAmbariViewsError'
-    });
   },
 
   loadAmbariViewsSuccess: function (data, opt, params) {
@@ -89,7 +88,7 @@ App.MainViewsController = Em.Controller.extend({
             instanceName: instance.ViewInstanceInfo.instance_name,
             href: instance.ViewInstanceInfo.context_path + "/"
           });
-          if( current_instance.visible ){
+          if (current_instance.visible) {
             instances.push(current_instance);
           }
         }, this);
@@ -104,8 +103,8 @@ App.MainViewsController = Em.Controller.extend({
     this.set('isDataLoaded', true);
   },
 
-  setView: function(event) {
-    if(event.context){
+  setView: function (event) {
+    if (event.context) {
       App.router.route('main/views/' + event.context.viewName + '/' + event.context.version + '/' + event.context.instanceName);
     }
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a808b19/ambari-web/app/views/main/admin/highAvailability/resourceManager/wizard_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/highAvailability/resourceManager/wizard_view.js b/ambari-web/app/views/main/admin/highAvailability/resourceManager/wizard_view.js
index cf03660..97320f6 100644
--- a/ambari-web/app/views/main/admin/highAvailability/resourceManager/wizard_view.js
+++ b/ambari-web/app/views/main/admin/highAvailability/resourceManager/wizard_view.js
@@ -21,6 +21,14 @@ var App = require('app');
 
 App.RMHighAvailabilityWizardView = Em.View.extend(App.WizardMenuMixin, {
 
+  templateName: require('templates/main/admin/highAvailability/resourceManager/wizard'),
+
+  /**
+   * @type {boolean}
+   * @default false
+   */
+  isLoaded: false,
+
   didInsertElement: function() {
     var currentStep = this.get('controller.currentStep');
     if (currentStep > 3) {
@@ -28,10 +36,6 @@ App.RMHighAvailabilityWizardView = Em.View.extend(App.WizardMenuMixin, {
     }
   },
 
-  templateName: require('templates/main/admin/highAvailability/resourceManager/wizard'),
-
-  isLoaded: false,
-
   willInsertElement: function() {
     this.set('isLoaded', false);
     this.loadHosts();
@@ -41,7 +45,7 @@ App.RMHighAvailabilityWizardView = Em.View.extend(App.WizardMenuMixin, {
    * load hosts from server
    */
   loadHosts: function () {
-    App.ajax.send({
+    return App.ajax.send({
       name: 'hosts.high_availability.wizard',
       data: {},
       sender: this,

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a808b19/ambari-web/test/controllers/main/alert_definitions_controller_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/alert_definitions_controller_test.js b/ambari-web/test/controllers/main/alert_definitions_controller_test.js
index a1f2b9a..ce0b2e1 100644
--- a/ambari-web/test/controllers/main/alert_definitions_controller_test.js
+++ b/ambari-web/test/controllers/main/alert_definitions_controller_test.js
@@ -70,4 +70,23 @@ describe('App.MainAlertDefinitionsController', function() {
 
   });
 
+  describe("#toggleState()", function() {
+
+    beforeEach(function() {
+      sinon.stub(App, 'showConfirmationFeedBackPopup', Em.clb);
+      sinon.stub(controller, 'toggleDefinitionState');
+    });
+    afterEach(function() {
+      App.showConfirmationFeedBackPopup.restore();
+      controller.toggleDefinitionState.restore();
+    });
+
+    it("toggleDefinitionState should be called", function() {
+      var def = Em.Object.create();
+      controller.toggleState({context: def});
+      expect(App.showConfirmationFeedBackPopup.calledOnce).to.be.true;
+      expect(controller.toggleDefinitionState.calledWith(def)).to.be.true;
+    });
+  });
+
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a808b19/ambari-web/test/controllers/main/host_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/host_test.js b/ambari-web/test/controllers/main/host_test.js
index 1242374..fce3c2c 100644
--- a/ambari-web/test/controllers/main/host_test.js
+++ b/ambari-web/test/controllers/main/host_test.js
@@ -17,6 +17,8 @@
  */
 
 var App = require('app');
+
+var testHelpers = require('test/helpers');
 require('utils/batch_scheduled_requests');
 require('controllers/main/host');
 require('mappers/server_data_mapper');
@@ -33,34 +35,49 @@ describe('MainHostController', function () {
     hostController.destroy();
   });
 
-  describe('#getRegExp()', function() {
+  describe("#totalCount()", function () {
+
+    it("TOTAL is undefined", function () {
+      hostController.set('hostsCountMap', {});
+      hostController.propertyDidChange('totalCount');
+      expect(hostController.get('totalCount')).to.be.equal(0);
+    });
+
+    it("TOTAL is 1", function () {
+      hostController.set('hostsCountMap', {TOTAL: 1});
+      hostController.propertyDidChange('totalCount');
+      expect(hostController.get('totalCount')).to.be.equal(1);
+    });
+  });
+
+  describe('#getRegExp()', function () {
     var message = '`{0}` should convert to `{1}`',
       tests = [
-        { value: '.*', expected: '.*' },
-        { value: '.', expected: '.*' },
-        { value: '.*.*', expected: '.*' },
-        { value: '*', expected: '^$' },
-        { value: '........', expected: '.*' },
-        { value: '........*', expected: '.*' },
-        { value: 'a1', expected: '.*a1.*' },
-        { value: 'a1.', expected: '.*a1.*' },
-        { value: 'a1...', expected: '.*a1.*' },
-        { value: 'a1.*', expected: '.*a1.*' },
-        { value: 'a1.*.a2.a3', expected: '.*a1.*.a2.a3.*' },
-        { value: 'a1.*.a2...a3', expected: '.*a1.*.a2...a3.*' }
+        {value: '.*', expected: '.*'},
+        {value: '.', expected: '.*'},
+        {value: '.*.*', expected: '.*'},
+        {value: '*', expected: '^$'},
+        {value: '........', expected: '.*'},
+        {value: '........*', expected: '.*'},
+        {value: 'a1', expected: '.*a1.*'},
+        {value: 'a1.', expected: '.*a1.*'},
+        {value: 'a1...', expected: '.*a1.*'},
+        {value: 'a1.*', expected: '.*a1.*'},
+        {value: 'a1.*.a2.a3', expected: '.*a1.*.a2.a3.*'},
+        {value: 'a1.*.a2...a3', expected: '.*a1.*.a2...a3.*'}
       ];
 
-    tests.forEach(function(test){
-      it(message.format(test.value, test.expected), function() {
+    tests.forEach(function (test) {
+      it(message.format(test.value, test.expected), function () {
         expect(hostController.getRegExp(test.value)).to.be.equal(test.expected);
       });
     });
   });
 
-  describe('#getQueryParameters', function() {
-    beforeEach(function() {
+  describe('#getQueryParameters', function () {
+    beforeEach(function () {
       sinon.spy(hostController, 'getRegExp');
-      sinon.stub(App.db, 'getFilterConditions', function() {
+      sinon.stub(App.db, 'getFilterConditions', function () {
         return [{
           iColumn: 1,
           skipFilter: false,
@@ -70,17 +87,17 @@ describe('MainHostController', function () {
       });
     });
 
-    afterEach(function() {
+    afterEach(function () {
       App.db.getFilterConditions.restore();
       hostController.getRegExp.restore();
     });
 
-    it('should call #getRegExp with value `someval` on host name filter', function() {
+    it('should call #getRegExp with value `someval` on host name filter', function () {
       hostController.getQueryParameters();
       expect(hostController.getRegExp.calledWith('someval')).to.ok;
     });
 
-    it('result should include host name filter converted value', function() {
+    it('result should include host name filter converted value', function () {
       expect(hostController.getQueryParameters().findProperty('key', 'Hosts/host_name').value).to.equal('.*someval.*');
     });
   });
@@ -88,9 +105,11 @@ describe('MainHostController', function () {
   describe('#getSortProps', function () {
 
     beforeEach(function () {
-      db = {mainHostController: [
-        {name: 'hostName', status: 'sorting'}
-      ]};
+      db = {
+        mainHostController: [
+          {name: 'hostName', status: 'sorting'}
+        ]
+      };
       sinon.stub(App.db, 'getSortingStatuses', function (k) {
         return db[k];
       });
@@ -111,4 +130,337 @@ describe('MainHostController', function () {
 
   });
 
+  describe("#updateStatusCounters()", function() {
+
+    it("isCountersUpdating is false", function() {
+      hostController.set('isCountersUpdating', false);
+      hostController.updateStatusCounters();
+      expect(testHelpers.findAjaxRequest('name', 'host.status.counters')).to.be.undefined;
+    });
+
+    it("isCountersUpdating is true", function() {
+      hostController.set('isCountersUpdating', true);
+      hostController.updateStatusCounters();
+      expect(testHelpers.findAjaxRequest('name', 'host.status.counters')).to.be.exist;
+    });
+  });
+
+  describe("#updateStatusCountersSuccessCallback()", function() {
+    var data = {
+      Clusters: {
+        health_report: {
+          'Host/host_status/HEALTHY': 1,
+          'Host/host_status/UNHEALTHY': 2,
+          'Host/host_status/ALERT': 3,
+          'Host/host_status/UNKNOWN': 4,
+          'Host/stale_config': 5,
+          'Host/maintenance_state': 6
+        },
+        total_hosts: 21
+      }
+    };
+
+    it("hostsCountMap should be set", function() {
+      hostController.updateStatusCountersSuccessCallback(data);
+      expect(hostController.get('hostsCountMap')).to.be.eql({
+        "HEALTHY": 1,
+        "UNHEALTHY": 2,
+        "ALERT": 3,
+        "UNKNOWN": 4,
+        "health-status-RESTART": 5,
+        "health-status-PASSIVE_STATE": 6,
+        "TOTAL": 21
+      });
+    });
+  });
+
+  describe("#getProperValue()", function() {
+
+    var testCases = [
+      {
+        input: '>1',
+        expected: '1'
+      },
+      {
+        input: '<1',
+        expected: '1'
+      },
+      {
+        input: '=1',
+        expected: '1'
+      },
+      {
+        input: '1',
+        expected: '1'
+      }
+    ];
+
+    testCases.forEach(function(test) {
+      it("value =" + test.input, function() {
+        expect(hostController.getProperValue(test.input)).to.be.equal(test.expected);
+      });
+    });
+
+  });
+
+  describe("#convertMemory()", function() {
+
+    beforeEach(function() {
+      sinon.stub(hostController, 'getProperValue', function(input) {
+        return input;
+      })
+    });
+    afterEach(function() {
+      hostController.getProperValue.restore();
+    });
+
+    var testCases = [
+      {
+        input: 'm',
+        expected: 'm'
+      },
+      {
+        input: '1',
+        expected: 1048576
+      },
+      {
+        input: '1g',
+        expected: 1048576
+      },
+      {
+        input: '1m',
+        expected: 1024
+      },
+      {
+        input: '1k',
+        expected: 1
+      }
+    ];
+
+    testCases.forEach(function(test) {
+      it("value =" + test.input, function() {
+        expect(hostController.convertMemory(test.input)).to.be.equal(test.expected);
+      });
+    });
+  });
+
+  describe("#convertMemoryToRange()", function() {
+
+    beforeEach(function() {
+      sinon.stub(hostController, 'rangeConvertNumber', function(arg1) {
+        return [arg1, arg1];
+      })
+    });
+    afterEach(function() {
+      hostController.rangeConvertNumber.restore();
+    });
+
+    var testCases = [
+      {
+        input: 'm',
+        expected: [0, 0]
+      },
+      {
+        input: '1',
+        expected: [1048576, 1048576]
+      },
+      {
+        input: '1g',
+        expected: [1048576, 1048576]
+      },
+      {
+        input: '1m',
+        expected: [1024, 1024]
+      },
+      {
+        input: '1k',
+        expected: [1, 1]
+      }
+    ];
+
+    testCases.forEach(function(test) {
+      it("value =" + test.input, function() {
+        expect(hostController.convertMemoryToRange(test.input)).to.be.eql(test.expected);
+      });
+    });
+  });
+
+  describe("#rangeConvertNumber()", function() {
+
+    var testCases = [
+      {
+        value: 'm',
+        scale: '',
+        expected: [0, 0]
+      },
+      {
+        value: 1,
+        scale: '',
+        expected: [0.995, 1.004999999]
+      },
+      {
+        value: 1,
+        scale: 'g',
+        expected: [0.995, 1.004999999]
+      },
+      {
+        value: 1,
+        scale: 'm',
+        expected: [0.95, 1.04999]
+      },
+      {
+        value: 1,
+        scale: 'k',
+        expected: [0.95, 1.04999]
+      }
+    ];
+
+    testCases.forEach(function(test) {
+      it("value = " + test.value + 'scale = ' + test.scale, function() {
+        expect(hostController.rangeConvertNumber(test.value, test.scale)).to.be.eql(test.expected);
+      });
+    });
+  });
+
+  describe("#getComparisonType()", function() {
+
+    var testCases = [
+      {
+        value: '1',
+        expected: 'EQUAL'
+      },
+      {
+        value: '>',
+        expected: 'MORE'
+      },
+      {
+        value: '<',
+        expected: 'LESS'
+      },
+      {
+        value: '=',
+        expected: 'EQUAL'
+      }
+    ];
+
+    testCases.forEach(function(test) {
+      it("value = " + test.value, function() {
+        expect(hostController.getComparisonType(test.value)).to.be.equal(test.expected);
+      });
+    });
+  });
+
+  describe("#filterByComponent()", function() {
+
+    beforeEach(function() {
+      sinon.stub(App.db, 'setFilterConditions');
+    });
+    afterEach(function() {
+      App.db.setFilterConditions.restore();
+    });
+
+    it("component is null", function() {
+      hostController.filterByComponent();
+      expect(App.db.setFilterConditions.called).to.be.false;
+    });
+
+    it("component exist", function() {
+      hostController.set('name', 'ctrl1');
+      hostController.filterByComponent(Em.Object.create({
+        componentName: 'C1'
+      }));
+      expect(App.db.setFilterConditions.calledWith('ctrl1', [{
+        iColumn: 6,
+        value: ['C1'],
+        type: 'multiple'
+      }])).to.be.true;
+    });
+  });
+
+  describe("#filterByStack()", function() {
+
+    beforeEach(function() {
+      sinon.stub(App.db, 'setFilterConditions');
+    });
+    afterEach(function() {
+      App.db.setFilterConditions.restore();
+    });
+
+    it("displayName is null", function() {
+      hostController.filterByStack(null, 'INSTALLED');
+      expect(App.db.setFilterConditions.called).to.be.false;
+    });
+
+    it("state is null", function() {
+      hostController.filterByStack('stack1', null);
+      expect(App.db.setFilterConditions.called).to.be.false;
+    });
+
+    it("stack and displayName exist", function() {
+      hostController.set('name', 'ctrl1');
+      hostController.filterByStack('stack1', 'INSTALLED');
+      expect(App.db.setFilterConditions.calledWith('ctrl1', [{
+        iColumn: 11,
+        value: [
+          {
+            property: 'repository_versions/RepositoryVersions/display_name',
+            value: 'stack1'
+          },
+          {
+            property: 'HostStackVersions/state',
+            value: 'INSTALLED'
+          }
+        ],
+        type: 'sub-resource'
+      }])).to.be.true;
+    });
+  });
+
+  describe("#goToHostAlerts()", function() {
+
+    beforeEach(function() {
+      sinon.stub(App.router, 'transitionTo');
+    });
+    afterEach(function() {
+      App.router.transitionTo.restore();
+    });
+
+    it("event is null", function() {
+      hostController.goToHostAlerts(null);
+      expect(App.router.transitionTo.called).to.be.false;
+    });
+
+    it("event.context is null", function() {
+      hostController.goToHostAlerts({context: null});
+      expect(App.router.transitionTo.called).to.be.false;
+    });
+
+    it("event.context is exist", function() {
+      hostController.goToHostAlerts({context: {}});
+      expect(App.router.transitionTo.calledWith('main.hosts.hostDetails.alerts', {})).to.be.true;
+    });
+  });
+
+  describe("#removeHosts()", function() {
+
+    it("host should be removed", function() {
+      var host1 = Em.Object.create({id: 'host1', isChecked: true});
+      hostController.set('content', [host1]);
+      hostController.set('fullContent', [host1]);
+      hostController.removeHosts();
+      expect(hostController.get('fullContent')).to.be.empty;
+    });
+  });
+
+  describe("#checkRemoved()", function() {
+
+    it("host should be removed", function() {
+      var host1 = Em.Object.create({id: 'host1', isChecked: true});
+      hostController.set('content', [host1]);
+      hostController.set('fullContent', [host1]);
+      hostController.checkRemoved('host1');
+      expect(hostController.get('fullContent')).to.be.empty;
+    });
+  });
+
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a808b19/ambari-web/test/controllers/main/service_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/service_test.js b/ambari-web/test/controllers/main/service_test.js
index ee90a0f..177aac8 100644
--- a/ambari-web/test/controllers/main/service_test.js
+++ b/ambari-web/test/controllers/main/service_test.js
@@ -113,6 +113,42 @@ describe('App.MainServiceController', function () {
     });
   });
 
+  describe("#isAllServicesInstalled", function() {
+
+    beforeEach(function() {
+      sinon.stub(App.StackService, 'find').returns([
+        Em.Object.create({serviceName: 'S1'})
+      ]);
+    });
+    afterEach(function() {
+      App.StackService.find.restore();
+    });
+
+    it("content is null", function() {
+      mainServiceController.reopen({
+        'content': null
+      });
+      mainServiceController.propertyDidChange('isAllServicesInstalled');
+      expect(mainServiceController.get('isAllServicesInstalled')).to.be.false;
+    });
+
+    it("content is empty", function() {
+      mainServiceController.reopen({
+        'content': []
+      });
+      mainServiceController.propertyDidChange('isAllServicesInstalled');
+      expect(mainServiceController.get('isAllServicesInstalled')).to.be.false;
+    });
+
+    it("content match stack services", function() {
+      mainServiceController.reopen({
+        'content': [Em.Object.create({serviceName: 'S1'})]
+      });
+      mainServiceController.propertyDidChange('isAllServicesInstalled');
+      expect(mainServiceController.get('isAllServicesInstalled')).to.be.true;
+    });
+  });
+
   describe('#cluster', function() {
 
     Em.A([
@@ -178,6 +214,12 @@ describe('App.MainServiceController', function () {
       expect(r).to.be.null;
     });
 
+    it('nothing disabled', function() {
+      var event = {target: {}}, query = 'query';
+      mainServiceController.startAllService(event).onPrimary(query);
+      expect(mainServiceController.allServicesCall.calledWith('STARTED', query));
+    });
+
   });
 
   describe('#stopAllService', function() {
@@ -202,6 +244,12 @@ describe('App.MainServiceController', function () {
       expect(r).to.be.null;
     });
 
+    it('nothing disabled', function() {
+      var event = {target: {}}, query = 'query';
+      mainServiceController.stopAllService(event).onPrimary(query);
+      expect(mainServiceController.allServicesCall.calledWith('STARTED', query));
+    });
+
   });
 
   describe('#startStopAllService', function() {
@@ -396,4 +444,259 @@ describe('App.MainServiceController', function () {
 
   });
 
+  describe("#restartAllServices()", function() {
+
+    beforeEach(function() {
+      sinon.stub(mainServiceController, 'silentStopAllServices');
+    });
+    afterEach(function() {
+      mainServiceController.silentStopAllServices.restore();
+    });
+
+    it("silentStopAllServices should be called", function() {
+      mainServiceController.restartAllServices();
+      expect(mainServiceController.silentStopAllServices.calledOnce).to.be.true;
+    });
+  });
+
+  describe("#silentStopAllServices()", function() {
+
+    it("App.ajax.send should be called", function() {
+      mainServiceController.silentStopAllServices();
+      var args = testHelpers.filterAjaxRequests('name', 'common.services.update');
+      expect(args[0][0]).to.eql({
+        name: 'common.services.update',
+        sender: mainServiceController,
+        data: {
+          context: App.BackgroundOperationsController.CommandContexts.STOP_ALL_SERVICES,
+          ServiceInfo: {
+            state: 'INSTALLED'
+          }
+        },
+        success: 'silentStopSuccess'
+      });
+    });
+  });
+
+  describe("#isStopAllServicesFailed()", function() {
+
+    beforeEach(function() {
+      this.mock = sinon.stub(App.Service, 'find');
+    });
+    afterEach(function() {
+      this.mock.restore();
+    });
+
+    it("one INSTALLED service", function() {
+      this.mock.returns([
+        Em.Object.create({workStatus: 'INSTALLED'})
+      ]);
+      expect(mainServiceController.isStopAllServicesFailed()).to.be.false;
+    });
+
+    it("one STOPPING service", function() {
+      this.mock.returns([
+        Em.Object.create({workStatus: 'STOPPING'})
+      ]);
+      expect(mainServiceController.isStopAllServicesFailed()).to.be.false;
+    });
+
+    it("one STARTED service and one INSTALLED", function() {
+      this.mock.returns([
+        Em.Object.create({workStatus: 'STARTED'}),
+        Em.Object.create({workStatus: 'INSTALLED'})
+      ]);
+      expect(mainServiceController.isStopAllServicesFailed()).to.be.true;
+    });
+
+    it("one STARTED service", function() {
+      this.mock.returns([
+        Em.Object.create({workStatus: 'STARTED'})
+      ]);
+      expect(mainServiceController.isStopAllServicesFailed()).to.be.true;
+    });
+  });
+
+  describe("#silentStopSuccess()", function() {
+    var mock = {
+      dataLoading: function() {
+        return {
+          done: function(callback) {
+            callback(true);
+          }
+        }
+      },
+      showPopup: Em.K
+    };
+
+    beforeEach(function() {
+      sinon.stub(App.router, 'get').returns(mock);
+      sinon.stub(Em.run, 'later', Em.clb);
+      sinon.spy(mock, 'showPopup');
+      sinon.stub(mainServiceController, 'silentStartAllServices');
+      mainServiceController.silentStopSuccess();
+    });
+    afterEach(function() {
+      App.router.get.restore();
+      Em.run.later.restore();
+      mock.showPopup.restore();
+      mainServiceController.silentStartAllServices.restore();
+    });
+
+    it("showPopup should be called", function() {
+      expect(mock.showPopup.calledOnce).to.be.true;
+    });
+
+    it("Em.run.later should be called", function() {
+      expect(Em.run.later.calledOnce).to.be.true;
+      expect(mainServiceController.get('shouldStart')).to.be.true;
+    });
+  });
+
+  describe("#silentStartAllServices()", function() {
+
+    beforeEach(function() {
+      this.mockRouter = sinon.stub(App.router, 'get');
+      this.mock = sinon.stub(mainServiceController, 'isStopAllServicesFailed');
+      mainServiceController.removeObserver('shouldStart', mainServiceController, 'silentStartAllServices');
+    });
+    afterEach(function() {
+      this.mockRouter.restore();
+      this.mock.restore();
+    });
+
+    it("allOperationsCount is 1", function() {
+      this.mockRouter.returns(Em.Object.create({
+        allOperationsCount: 1
+      }));
+      mainServiceController.silentStartAllServices();
+      expect(testHelpers.findAjaxRequest('name', 'common.services.update')).to.be.undefined;
+    });
+
+    it("shouldStart is false", function() {
+      this.mockRouter.returns(Em.Object.create({
+        allOperationsCount: 0
+      }));
+      mainServiceController.set('shouldStart', false);
+      mainServiceController.silentStartAllServices();
+      expect(testHelpers.findAjaxRequest('name', 'common.services.update')).to.be.undefined;
+    });
+
+    it("isStopAllServicesFailed returns true", function() {
+      this.mockRouter.returns(Em.Object.create({
+        allOperationsCount: 0
+      }));
+      mainServiceController.set('shouldStart', true);
+      this.mock.returns(true);
+      mainServiceController.silentStartAllServices();
+      expect(testHelpers.findAjaxRequest('name', 'common.services.update')).to.be.undefined;
+    });
+
+    it("App.ajax.send should be called", function() {
+      this.mockRouter.returns(Em.Object.create({
+        allOperationsCount: 0
+      }));
+      mainServiceController.set('shouldStart', true);
+      this.mock.returns(false);
+      mainServiceController.silentStartAllServices();
+      var args = testHelpers.filterAjaxRequests('name', 'common.services.update');
+      expect(args[0][0]).to.be.eql({
+        name: 'common.services.update',
+        sender: mainServiceController,
+        data: {
+          context: App.BackgroundOperationsController.CommandContexts.START_ALL_SERVICES,
+          ServiceInfo: {
+            state: 'STARTED'
+          }
+        },
+        success: 'silentCallSuccessCallback'
+      });
+      expect(mainServiceController.get('shouldStart')).to.be.false;
+    });
+  });
+
+  describe("#silentCallSuccessCallback()", function () {
+    var mock = {
+      dataLoading: function () {
+        return {
+          done: function (callback) {
+            callback(true);
+          }
+        }
+      },
+      showPopup: Em.K
+    };
+
+    beforeEach(function () {
+      sinon.stub(App.router, 'get').returns(mock);
+      sinon.spy(mock, 'showPopup');
+    });
+    afterEach(function () {
+      App.router.get.restore();
+      mock.showPopup.restore();
+    });
+
+    it("showPopup should be called", function () {
+      mainServiceController.silentCallSuccessCallback();
+      expect(mock.showPopup.calledOnce).to.be.true;
+    });
+  });
+
+  describe("#allServicesCallSuccessCallback()", function () {
+    var mock = {
+      dataLoading: function () {
+        return {
+          done: function (callback) {
+            callback(true);
+          }
+        }
+      },
+      showPopup: Em.K
+    };
+
+    beforeEach(function () {
+      sinon.stub(App.router, 'get').returns(mock);
+      sinon.spy(mock, 'showPopup');
+    });
+    afterEach(function () {
+      App.router.get.restore();
+      mock.showPopup.restore();
+    });
+
+    it("showPopup should be called", function () {
+      var params = {
+        query: Em.Object.create()
+      };
+      mainServiceController.allServicesCallSuccessCallback({}, {}, params);
+      expect(mock.showPopup.calledOnce).to.be.true;
+      expect(params.query.get('status')).to.be.equal('SUCCESS');
+    });
+  });
+
+  describe("#restartAllRequiredSuccessCallback()", function () {
+    var mock = {
+      dataLoading: function () {
+        return {
+          done: function (callback) {
+            callback(true);
+          }
+        }
+      },
+      showPopup: Em.K
+    };
+
+    beforeEach(function () {
+      sinon.stub(App.router, 'get').returns(mock);
+      sinon.spy(mock, 'showPopup');
+    });
+    afterEach(function () {
+      App.router.get.restore();
+      mock.showPopup.restore();
+    });
+
+    it("showPopup should be called", function () {
+      mainServiceController.restartAllRequiredSuccessCallback();
+      expect(mock.showPopup.calledOnce).to.be.true;
+    });
+  });
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a808b19/ambari-web/test/controllers/main/views_controller_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/views_controller_test.js b/ambari-web/test/controllers/main/views_controller_test.js
index 41384d3..4242750 100644
--- a/ambari-web/test/controllers/main/views_controller_test.js
+++ b/ambari-web/test/controllers/main/views_controller_test.js
@@ -50,4 +50,106 @@ describe('MainViewsController', function () {
     })
   });
 
+  describe('#loadAmbariViewsSuccess()', function () {
+
+    it('data has items', function () {
+      mainViewsController.loadAmbariViewsSuccess({items: [{}]});
+      var args = testHelpers.findAjaxRequest('name', 'views.instances');
+      expect(args).to.exists;
+    });
+
+    it('data is empty', function () {
+      mainViewsController.loadAmbariViewsSuccess({items: []});
+      var args = testHelpers.findAjaxRequest('name', 'views.instances');
+      expect(args).to.not.exists;
+      expect(mainViewsController.get('ambariViews')).to.be.empty;
+      expect(mainViewsController.get('isDataLoaded')).to.be.true;
+    });
+  });
+
+  describe('#loadAmbariViewsError()', function () {
+
+    it('ambariViews should be empty', function () {
+      mainViewsController.loadAmbariViewsError();
+      expect(mainViewsController.get('ambariViews')).to.be.empty;
+      expect(mainViewsController.get('isDataLoaded')).to.be.true;
+    });
+  });
+
+  describe("#loadViewInstancesSuccess()", function () {
+
+    var data = {
+      items: [
+        {
+          versions: [
+            {
+              instances: [
+                {
+                  ViewInstanceInfo: {
+                    icon_path: 'icon_path1',
+                    label: 'label1',
+                    visible: true,
+                    version: '1.0',
+                    description: 'desc1',
+                    viewName: 'view_name1',
+                    instanceName: 'instance_name1',
+                    context_path: 'path1'
+                  }
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    };
+
+    it("should parse view instance data", function () {
+      mainViewsController.loadViewInstancesSuccess(data);
+      expect(JSON.parse(JSON.stringify(mainViewsController.get('ambariViews')))).to.be.eql([{
+        "iconPath": "icon_path1",
+        "label": "label1",
+        "visible": true,
+        "version": "1.0",
+        "description": "desc1",
+        "href": "path1/"
+      }]);
+      expect(mainViewsController.get('isDataLoaded')).to.be.true;
+    });
+  });
+
+  describe('#loadViewInstancesError()', function () {
+
+    it('ambariViews should be empty', function () {
+      mainViewsController.loadViewInstancesError();
+      expect(mainViewsController.get('ambariViews')).to.be.empty;
+      expect(mainViewsController.get('isDataLoaded')).to.be.true;
+    });
+  });
+
+  describe("#setView", function () {
+
+    beforeEach(function () {
+      sinon.stub(App.router, 'route');
+    });
+    afterEach(function () {
+      App.router.route.restore();
+    });
+
+    it("no context", function () {
+      mainViewsController.setView({});
+      expect(App.router.route.called).to.be.false;
+    });
+
+    it("context exist", function () {
+      mainViewsController.setView({
+        context: {
+          viewName: 'view1',
+          version: '1',
+          instanceName: 'instance1'
+        }
+      });
+      expect(App.router.route.calledWith('main/views/view1/1/instance1')).to.be.true;
+    });
+  });
+
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a808b19/ambari-web/test/views/main/admin/highAvailability/resourceManager/step3_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/admin/highAvailability/resourceManager/step3_view_test.js b/ambari-web/test/views/main/admin/highAvailability/resourceManager/step3_view_test.js
new file mode 100644
index 0000000..5b8972c
--- /dev/null
+++ b/ambari-web/test/views/main/admin/highAvailability/resourceManager/step3_view_test.js
@@ -0,0 +1,49 @@
+/**
+ * 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('views/main/admin/highAvailability/resourceManager/step3_view');
+
+describe('App.RMHighAvailabilityWizardStep3View', function () {
+  var view;
+
+  beforeEach(function() {
+    view = App.RMHighAvailabilityWizardStep3View.create({
+      controller: Em.Object.create({
+        content: Em.Object.create(),
+        loadStep: Em.K
+      })
+    });
+  });
+
+  describe("#didInsertElement()", function () {
+
+    beforeEach(function () {
+      sinon.spy(view.get('controller'), 'loadStep');
+    });
+    afterEach(function () {
+      view.get('controller').loadStep.restore();
+    });
+
+    it("call loadStep", function () {
+      view.didInsertElement();
+      expect(view.get('controller').loadStep.calledOnce).to.be.true;
+    });
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a808b19/ambari-web/test/views/main/admin/highAvailability/resourceManager/wizard_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/admin/highAvailability/resourceManager/wizard_view_test.js b/ambari-web/test/views/main/admin/highAvailability/resourceManager/wizard_view_test.js
new file mode 100644
index 0000000..ad859f1
--- /dev/null
+++ b/ambari-web/test/views/main/admin/highAvailability/resourceManager/wizard_view_test.js
@@ -0,0 +1,137 @@
+/**
+ * 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');
+var testHelpers = require('test/helpers');
+require('views/main/admin/highAvailability/resourceManager/wizard_view');
+
+describe('App.RMHighAvailabilityWizardView', function () {
+  var view;
+
+  beforeEach(function() {
+    view = App.RMHighAvailabilityWizardView.create({
+      controller: Em.Object.create({
+        content: Em.Object.create(),
+        setLowerStepsDisable: Em.K
+      })
+    });
+  });
+
+  describe("#didInsertElement()", function () {
+
+    beforeEach(function () {
+      sinon.spy(view.get('controller'), 'setLowerStepsDisable');
+    });
+    afterEach(function () {
+      view.get('controller').setLowerStepsDisable.restore();
+    });
+
+    it("setLowerStepsDisable should not be called", function () {
+      view.set('controller.currentStep', 3);
+      view.didInsertElement();
+      expect(view.get('controller').setLowerStepsDisable.called).to.be.false;
+    });
+
+    it("call setLowerStepsDisable", function () {
+      view.set('controller.currentStep', 4);
+      view.didInsertElement();
+      expect(view.get('controller').setLowerStepsDisable.calledOnce).to.be.true;
+    });
+  });
+
+  describe("#willInsertElement", function() {
+
+    beforeEach(function() {
+      sinon.stub(view, 'loadHosts');
+    });
+    afterEach(function() {
+      view.loadHosts.restore();
+    });
+
+    it("loadHosts should be called", function() {
+      view.willInsertElement();
+      expect(view.loadHosts.calledOnce).to.be.true;
+      expect(view.get('isLoaded')).to.be.false;
+    });
+  });
+
+  describe("#loadHosts()", function() {
+
+    it("App.ajax.send should be called", function() {
+      view.loadHosts();
+      var args = testHelpers.findAjaxRequest('name', 'hosts.high_availability.wizard');
+      expect(args).to.be.exist;
+    });
+  });
+
+  describe("#loadHostsSuccessCallback()", function() {
+    var data = {
+      items: [
+        {
+          Hosts: {
+            host_name: 'host1',
+            cpu_count: 1,
+            total_mem: 1,
+            disk_info: {}
+          }
+        }
+      ]
+    };
+
+    beforeEach(function() {
+      sinon.stub(App.db, 'setHosts');
+    });
+    afterEach(function() {
+      App.db.setHosts.restore();
+    });
+
+    it("App.db.setHosts should be called", function () {
+      view.loadHostsSuccessCallback(data);
+      expect(view.get('isLoaded')).to.be.true;
+      expect(view.get('controller.content.hosts')).to.be.eql({
+        "host1": {
+          "name": "host1",
+          "cpu": 1,
+          "memory": 1,
+          "disk_info": {},
+          "bootStatus": "REGISTERED",
+          "isInstalled": true
+        }
+      });
+      expect(App.db.setHosts.calledWith({
+        "host1": {
+          "name": "host1",
+          "cpu": 1,
+          "memory": 1,
+          "disk_info": {},
+          "bootStatus": "REGISTERED",
+          "isInstalled": true
+        }
+      })).to.be.true;
+    });
+  });
+
+  describe("#loadHostsErrorCallback()", function() {
+
+    it("isLoaded should be true", function() {
+      view.loadHostsErrorCallback();
+      expect(view.get('isLoaded')).to.be.true;
+    });
+  });
+});