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

git commit: AMBARI-5508. Unit tests for steps 10. (onechiporenko)

Repository: ambari
Updated Branches:
  refs/heads/trunk fd73398b1 -> 8865d248e


AMBARI-5508. Unit tests for steps 10. (onechiporenko)


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

Branch: refs/heads/trunk
Commit: 8865d248eee1e0e9a53f913f2ec9d2131a786ad7
Parents: fd73398
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Fri Apr 18 16:03:47 2014 +0300
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Fri Apr 18 16:06:18 2014 +0300

----------------------------------------------------------------------
 ambari-web/app/assets/test/tests.js             |   1 +
 .../app/controllers/wizard/step10_controller.js | 334 +++++------------
 ambari-web/app/templates/wizard/step10.hbs      |  24 +-
 ambari-web/app/views/wizard/step10_view.js      |   3 +-
 ambari-web/test/installer/step10_test.js        | 374 ++++++++++++++++++-
 .../test/views/wizard/step10_view_test.js       |  36 ++
 6 files changed, 524 insertions(+), 248 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/8865d248/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 d74422a..385d76f 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -137,6 +137,7 @@ require('test/views/wizard/step2_view_test');
 require('test/views/wizard/step3_view_test');
 require('test/views/wizard/step5_view_test');
 require('test/views/wizard/step9_view_test');
+require('test/views/wizard/step10_view_test');
 require('test/models/host_test');
 require('test/models/host_component_test');
 require('test/models/rack_test');

http://git-wip-us.apache.org/repos/asf/ambari/blob/8865d248/ambari-web/app/controllers/wizard/step10_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step10_controller.js b/ambari-web/app/controllers/wizard/step10_controller.js
index 7b760ae..2e6860e 100644
--- a/ambari-web/app/controllers/wizard/step10_controller.js
+++ b/ambari-web/app/controllers/wizard/step10_controller.js
@@ -19,16 +19,32 @@
 var App = require('app');
 
 App.WizardStep10Controller = Em.Controller.extend({
+
+  /**
+   * List of data about installed cluster components (hosts, services etc)
+   * @type {Ember.Object[]}
+   */
   clusterInfo: [],
 
-  isNagiosRestartRequired: function() {
+  /**
+   * Show message about required Nagios restart if installWizard used and Nagios is installed
+   * @type {bool}
+   */
+  isNagiosRestartRequired: function () {
     return this.get('content.controllerName') !== 'installerController' && App.Service.find('NAGIOS').get('isLoaded');
   }.property(),
 
+  /**
+   * Clear <code>clusterInfo</code>
+   * @method clearStep
+   */
   clearStep: function () {
     this.get('clusterInfo').clear();
   },
 
+  /**
+   * @method loadStep
+   */
   loadStep: function () {
     console.log("TRACE: Loading step10: Summary Page");
     this.clearStep();
@@ -44,6 +60,11 @@ App.WizardStep10Controller = Em.Controller.extend({
     }
   },
 
+  /**
+   * Get list of clusterInfo object about registered hosts
+   * @returns {{id: number, color: string, displayStatement: string, status: array}}
+   * @method loadRegisteredHosts
+   */
   loadRegisteredHosts: function () {
     var masterHosts = this.get('content.masterComponentHosts').mapProperty('hostName').uniq();
     var slaveHosts = this.get('content.slaveComponentHosts');
@@ -54,7 +75,7 @@ App.WizardStep10Controller = Em.Controller.extend({
     slaveHosts = hostObj.mapProperty('hostName').uniq();
     var registeredHosts = App.Host.find().mapProperty('hostName').concat(masterHosts.concat(slaveHosts)).uniq();
     var registerHostsStatement = Em.I18n.t('installer.step10.hostsSummary').format(registeredHosts.length);
-    var registerHostsObj = Ember.Object.create({
+    var registerHostsObj = Em.Object.create({
       id: 1,
       color: 'text-info',
       displayStatement: registerHostsStatement,
@@ -65,17 +86,25 @@ App.WizardStep10Controller = Em.Controller.extend({
     return registerHostsObj;
   },
 
-  loadInstalledHosts: function (host) {
+  /**
+   * Push info about installed hosts to <code>clusterInfo</code>
+   * @method loadInstalledHosts
+   */
+  loadInstalledHosts: function () {
     var hosts = this.get('content.hosts');
     var hostsInfo = [];
     for (var index in hosts) {
-      hostsInfo.pushObject(hosts[index]);
+      if (hosts.hasOwnProperty(index)) {
+        hostsInfo.pushObject(hosts[index]);
+      }
     }
     var succeededHosts = hostsInfo.filterProperty('status', 'success');
-    var warnedHosts = hostsInfo.filterProperty('status', 'warning').concat(hostsInfo.filterProperty('status', 'failed'));
+    var warnedHosts = hostsInfo.filter(function(host) {
+      return ['warning', 'failed'].contains(host.get('status'));
+    });
     if (succeededHosts.length) {
       var successStatement = Em.I18n.t('installer.step10.servicesSummary').format(succeededHosts.length) + ((succeededHosts.length > 1) ? Em.I18n.t('installer.step8.hosts') : Em.I18n.t('installer.step8.host'));
-      this.get('clusterInfo').findProperty('id', 1).get('status').pushObject(Ember.Object.create({
+      this.get('clusterInfo').findProperty('id', 1).get('status').pushObject(Em.Object.create({
         id: 1,
         color: 'text-success',
         displayStatement: successStatement
@@ -84,67 +113,60 @@ App.WizardStep10Controller = Em.Controller.extend({
 
     if (warnedHosts.length) {
       var warnStatement = warnedHosts.length + Em.I18n.t('installer.step10.warnings');
-      this.get('clusterInfo').findProperty('id', 1).get('status').pushObject(Ember.Object.create({
+      this.get('clusterInfo').findProperty('id', 1).get('status').pushObject(Em.Object.create({
         id: 2,
         color: 'text-warning',
         displayStatement: warnStatement,
         statements: []
       }));
-
       warnedHosts.forEach(function (_host) {
-        var clusterState;
-        console.log("Content.cluster.status is: " + this.get('content.cluster.status'));
+        var clusterState = '';
         if (this.get('content.cluster.status') === 'INSTALL FAILED') {
           clusterState = Em.I18n.t('installer.step10.clusterState.installing');
-        } else if (this.get('content.cluster.status') === 'START FAILED') {
-          clusterState = Em.I18n.t('installer.step10.clusterState.starting');
         }
-        var failedTasks = _host.tasks.filterProperty('Tasks.status', 'FAILED');
-        failedTasks.forEach(function (_task) {
-          var taskStatement = clusterState + App.format.role(_task.Tasks.role) + Em.I18n.t('installer.step10.taskStatus.failed') + _host.name;
-          this.get('clusterInfo').findProperty('id', 1).get('status').findProperty('id', 2).get('statements').pushObject(Ember.Object.create({
-            status: 'failed',
-            color: 'text-info',
-            displayStatement: taskStatement
-          }));
-        }, this);
-
-        var abortedTasks = _host.tasks.filterProperty('Tasks.status', 'ABORTED');
-        abortedTasks.forEach(function (_task) {
-          var abortStatement = clusterState + App.format.role(_task.Tasks.role) + Em.I18n.t('installer.step10.taskStatus.aborted') + _host.name;
-          this.get('clusterInfo').findProperty('id', 1).get('status').findProperty('id', 2).get('statements').pushObject(Ember.Object.create({
-            status: 'aborted',
-            color: 'text-info',
-            displayStatement: abortStatement
-          }));
-        }, this);
+        else {
+          if (this.get('content.cluster.status') === 'START FAILED') {
+            clusterState = Em.I18n.t('installer.step10.clusterState.starting');
+          }
+        }
 
-        var timedOutTasks = _host.tasks.filterProperty('Tasks.status', 'TIMEDOUT');
-        timedOutTasks.forEach(function (_task) {
-          var timedOutStatement = clusterState + App.format.role(_task.Tasks.role) + Em.I18n.t('installer.step10.taskStatus.timedOut') + _host.name;
-          this.get('clusterInfo').findProperty('id', 1).get('status').findProperty('id', 2).get('statements').pushObject(Ember.Object.create({
-            status: 'timedout',
-            color: 'text-info',
-            displayStatement: timedOutStatement
-          }));
-        }, this);
+        var self = this;
+        Em.A([
+            {Tst: 'FAILED', st: 'failed'},
+            {Tst: 'ABORTED', st: 'aborted'},
+            {Tst: 'TIMEDOUT', st: 'timedout'}
+          ]).forEach(function (s) {
+            _host.tasks.filterProperty('Tasks.status', s.Tst).forEach(function (_task) {
+              var statement = clusterState + App.format.role(_task.Tasks.role) + Em.I18n.t('installer.step10.taskStatus.failed') + _host.name;
+              self.get('clusterInfo').findProperty('id', 1).get('status').findProperty('id', 2).get('statements').pushObject(Em.Object.create({
+                status: s.st,
+                color: 'text-info',
+                displayStatement: statement
+              }));
+            });
+          });
       }, this);
     }
   },
 
+  /**
+   * Push info about installed/failed master components to <code>clusterInfo</code>
+   * @returns {bool}
+   * @method loadMasterComponents
+   */
   loadMasterComponents: function () {
     var components = this.get('content.masterComponentHosts');
-    var statement;
     if (this.get('content.cluster.status') === 'INSTALL FAILED') {
-      this.get('clusterInfo').pushObject(Ember.Object.create({
+      this.get('clusterInfo').pushObject(Em.Object.create({
         id: 2,
         displayStatement: Em.I18n.t('installer.step10.installStatus.failed'),
         color: 'text-error',
         status: []
       }));
       return false;
-    } else {
-      this.get('clusterInfo').pushObject(Ember.Object.create({
+    }
+    else {
+      this.get('clusterInfo').pushObject(Em.Object.create({
         id: 2,
         displayStatement: Em.I18n.t('installer.step10.installStatus.installed'),
         color: 'text-success',
@@ -154,207 +176,45 @@ App.WizardStep10Controller = Em.Controller.extend({
 
     console.log('STEP10 master components:  ' + JSON.stringify(components));
     components.forEach(function (_component) {
-      var component = Ember.Object.create(_component);
-      switch (component.component) {
-        case 'NAMENODE':
-          this.loadNn(component);
-          break;
-        case 'SECONDARY_NAMENODE':
-          this.loadSnn(component);
-          break;
-        case 'JOBTRACKER' :
-          this.loadJt(component);
-          break;
-        case 'HISTORYSERVER':
-          this.loadHS(component);
-          break;
-        case 'RESOURCEMANAGER':
-          this.loadRM(component);
-          break;
-        case 'ZOOKEEPER_SERVER' :
-          // TODO: Fix this; redundant entries and wrong number
-          //this.loadZk(component);
-          break;
-        case 'HBASE_MASTER':
-          this.loadHb(component);
-          break;
-        case 'HIVE_SERVER':
-          this.loadHiveServer(component);
-          break;
-        case 'OOZIE_SERVER':
-          this.loadOozieServer(component);
-          break;
-        case 'GANGLIA_SERVER':
-          this.loadGanglia(component);
-          break;
-        case 'NAGIOS_SERVER':
-          this.loadNagios(component);
-          break;
+      var component = Em.Object.create(_component);
+      if (['NAMENODE', 'SECONDARY_NAMENODE', 'JOBTRACKER', 'HISTORYSERVER', 'RESOURCEMANAGER', 'HBASE_MASTER',
+        'HIVE_SERVER', 'OOZIE_SERVER', 'GANGLIA_SERVER', 'NAGIOS_SERVER'].contains(component.component)) {
+        this.loadMasterComponent(component);
       }
     }, this);
     return true;
   },
 
-  loadHS: function (component) {
-    if (component.get('hostName')) {
-      var statement = Em.I18n.t('installer.step10.master.historyServer') + component.get('hostName');
-      this.get('clusterInfo').findProperty('id', 2).get('status').pushObject(Ember.Object.create({
-        id: 1,
-        color: 'text-info',
-        displayStatement: statement
-      }));
-    } else {
-      console.log('ERROR: no host name assigned to HistoryServer component');
-    }
-  },
-
-  loadRM: function (component) {
+  /**
+   * Push component info to <code>clusterInfo</code>
+   * @param {Ember.Object} component
+   * @method loadMasterComponent
+   */
+  loadMasterComponent: function (component) {
     if (component.get('hostName')) {
-      var statement = Em.I18n.t('installer.step10.master.resourceManager') + component.get('hostName');
-      this.get('clusterInfo').findProperty('id', 2).get('status').pushObject(Ember.Object.create({
+      var statement = Em.I18n.t('installer.step10.master.installedOn').format(component.get('display_name'), component.get('hostName'));
+      this.get('clusterInfo').findProperty('id', 2).get('status').pushObject(Em.Object.create({
         id: 1,
         color: 'text-info',
         displayStatement: statement
       }));
-    } else {
-      console.log('ERROR: no host name assigned to ResourceManager component');
     }
   },
 
-  loadNn: function (component) {
-    if (component.get('hostName')) {
-      var statement = Em.I18n.t('installer.step10.master.nameNode') + component.get('hostName');
-      this.get('clusterInfo').findProperty('id', 2).get('status').pushObject(Ember.Object.create({
-        id: 1,
-        color: 'text-info',
-        displayStatement: statement
-      }));
-    } else {
-      console.log('ERROR: no host name assigned to NameNode component');
-    }
-  },
-
-  loadSnn: function (component) {
-    if (component.get('hostName')) {
-      var statement = Em.I18n.t('installer.step10.master.secondaryNameNode') + component.get('hostName');
-      this.get('clusterInfo').findProperty('id', 2).get('status').pushObject(Ember.Object.create({
-        id: 1,
-        color: 'text-info',
-        displayStatement: statement
-      }));
-    } else {
-      console.log('ERROR: no host name assigned to SecondaryNameNode component');
-    }
-  },
-
-  loadJt: function (component) {
-    if (component.get('hostName')) {
-      var statement = Em.I18n.t('installer.step10.master.jobTracker') + component.get('hostName');
-      this.get('clusterInfo').findProperty('id', 2).get('status').pushObject(Ember.Object.create({
-        id: 1,
-        color: 'text-info',
-        displayStatement: statement
-      }));
-    } else {
-      console.log('ERROR: no host name assigned to JobTracker component');
-    }
-  },
-
-  loadZk: function (component) {
-    var hostLength = component.get('hostName').length;
-    if (hostLength) {
-      var hostVal;
-      if (hostLength === 1) {
-        hostVal = Em.I18n.t('installer.step8.host');
-      } else {
-        hostVal = Em.I18n.t('installer.step8.hosts');
-      }
-      var statement = Em.I18n.t('installer.step10.master.zooKeeper') + component.get('hostName').length + ' ' + hostVal;
-      this.get('clusterInfo').findProperty('id', 2).get('status').pushObject(Ember.Object.create({
-        id: 1,
-        color: 'text-info',
-        displayStatement: statement
-      }));
-    } else {
-      console.log('ERROR: no host name assigned to Zookeeper component');
-    }
-  },
-
-  loadHb: function (component) {
-    if (component.get('hostName')) {
-      var statement = Em.I18n.t('installer.step10.master.hbase') + component.get('hostName');
-      this.get('clusterInfo').findProperty('id', 2).get('status').pushObject(Ember.Object.create({
-        id: 1,
-        color: 'text-info',
-        displayStatement: statement
-      }));
-    } else {
-      console.log('ERROR: no host name assigned to HBase Master component');
-    }
-  },
-
-  loadHiveServer: function (component) {
-    if (component.get('hostName')) {
-      var statement = Em.I18n.t('installer.step10.master.hiveMetastore') + component.get('hostName');
-      this.get('clusterInfo').findProperty('id', 2).get('status').pushObject(Ember.Object.create({
-        id: 1,
-        color: 'text-info',
-        displayStatement: statement
-      }));
-    } else {
-      console.log('ERROR: no host name assigned to Hive server component');
-    }
-  },
-
-  loadOozieServer: function (component) {
-    if (component.get('hostName')) {
-      var statement = Em.I18n.t('installer.step10.master.oozie') + component.get('hostName');
-      this.get('clusterInfo').findProperty('id', 2).get('status').pushObject(Ember.Object.create({
-        id: 1,
-        color: 'text-info',
-        displayStatement: statement
-      }));
-    } else {
-      console.log('ERROR: no host name assigned to Oozie server component');
-    }
-  },
-
-  loadGanglia: function (component) {
-    if (component.get('hostName')) {
-      var statement = Em.I18n.t('installer.step10.master.ganglia') + component.get('hostName');
-      this.get('clusterInfo').findProperty('id', 2).get('status').pushObject(Ember.Object.create({
-        id: 1,
-        color: 'text-info',
-        displayStatement: statement
-      }));
-    } else {
-      console.log('ERROR: no host name assigned to Ganglia server component');
-    }
-  },
-
-  loadNagios: function (component) {
-    if (component.get('hostName')) {
-      var statement = Em.I18n.t('installer.step10.master.nagios') + component.get('hostName');
-      this.get('clusterInfo').findProperty('id', 2).get('status').pushObject(Ember.Object.create({
-        id: 1,
-        color: 'text-info',
-        displayStatement: statement
-      }));
-    } else {
-      console.log('ERROR: no host name assigned to Nagios server component');
-    }
-  },
-
-  loadStartedServices: function (component) {
+  /**
+   * Push info about installed/started/failed services to <code>clusterInfo</code>
+   * @returns {bool}
+   * @method loadStartedServices
+   */
+  loadStartedServices: function () {
     if (this.get('content.cluster.status') === 'STARTED') {
-      var statement = Em.I18n.t('installer.step10.startStatus.started');
-      this.get('clusterInfo').pushObject(Ember.Object.create({
+      this.get('clusterInfo').pushObject(Em.Object.create({
         id: 3,
         color: 'text-success',
         displayStatement: Em.I18n.t('installer.step10.startStatus.started'),
         status: []
       }));
-      this.get('clusterInfo').pushObject(Ember.Object.create({
+      this.get('clusterInfo').pushObject(Em.Object.create({
         id: 4,
         color: 'text-success',
         displayStatement: Em.I18n.t('installer.step10.startStatus.passed'),
@@ -362,7 +222,7 @@ App.WizardStep10Controller = Em.Controller.extend({
       }));
       return true;
     } else {
-      this.get('clusterInfo').pushObject(Ember.Object.create({
+      this.get('clusterInfo').pushObject(Em.Object.create({
         id: 3,
         color: 'text-error',
         displayStatement: Em.I18n.t('installer.step10.startStatus.failed'),
@@ -372,9 +232,12 @@ App.WizardStep10Controller = Em.Controller.extend({
     }
   },
 
+  /**
+   * Push install time to <code>clusterInfo</code>
+   * @method loadInstallTime
+   */
   loadInstallTime: function () {
-    var statement;
-    var time;
+    var statement, time;
     if (this.get('content.cluster.installTime')) {
       time = this.calculateInstallTime(this.get('content.cluster.installTime'));
       if (time.minutes !== 0) {
@@ -382,7 +245,7 @@ App.WizardStep10Controller = Em.Controller.extend({
       } else {
         statement = Em.I18n.t('installer.step10.installTime.seconds').format(time.seconds);
       }
-      this.get('clusterInfo').pushObject(Ember.Object.create({
+      this.get('clusterInfo').pushObject(Em.Object.create({
         id: 5,
         color: 'text-info',
         displayStatement: statement,
@@ -390,7 +253,14 @@ App.WizardStep10Controller = Em.Controller.extend({
       }));
     }
   },
-  calculateInstallTime: function(installTime){
+
+  /**
+   * Get used time for install process
+   * @param {number} installTime
+   * @returns {{minutes: *, seconds: *}}
+   * @method calculateInstallTime
+   */
+  calculateInstallTime: function (installTime) {
     var secondsPerMinute = 60;
     var minutes = Math.floor(installTime);
     var seconds = Math.floor((installTime - minutes) * secondsPerMinute);
@@ -399,5 +269,5 @@ App.WizardStep10Controller = Em.Controller.extend({
       seconds: seconds
     }
   }
-});
 
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/8865d248/ambari-web/app/templates/wizard/step10.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step10.hbs b/ambari-web/app/templates/wizard/step10.hbs
index b0f8cff..80afa5c 100644
--- a/ambari-web/app/templates/wizard/step10.hbs
+++ b/ambari-web/app/templates/wizard/step10.hbs
@@ -31,18 +31,18 @@
       <li>
         <span {{bindAttr class="item.color"}}>{{item.displayStatement}}</span>
         <ul>
-        {{#each status in item.status}}
-          <li>
-            <span {{bindAttr class="status.color"}}>{{status.displayStatement}}</span>
-            <ul>
-              {{#each statement in status.statements}}
-              <li>
-                <span {{bindAttr class="status.color"}}>{{statement.displayStatement}}</span>
-              </li>
-              {{/each}}
-            </ul>
-          </li>
-        {{/each}}
+          {{#each status in item.status}}
+            <li>
+              <span {{bindAttr class="status.color"}}>{{status.displayStatement}}</span>
+              <ul>
+                {{#each statement in status.statements}}
+                  <li>
+                    <span {{bindAttr class="status.color"}}>{{statement.displayStatement}}</span>
+                  </li>
+                {{/each}}
+              </ul>
+            </li>
+          {{/each}}
         </ul>
       </li>
     {{/each}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/8865d248/ambari-web/app/views/wizard/step10_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/wizard/step10_view.js b/ambari-web/app/views/wizard/step10_view.js
index a93d982..a48353b 100644
--- a/ambari-web/app/views/wizard/step10_view.js
+++ b/ambari-web/app/views/wizard/step10_view.js
@@ -24,8 +24,7 @@ App.WizardStep10View = Em.View.extend({
   templateName: require('templates/wizard/step10'),
 
   didInsertElement: function () {
-    var controller = this.get('controller');
-    controller.loadStep();
+    this.get('controller').loadStep();
   }
 
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/8865d248/ambari-web/test/installer/step10_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/installer/step10_test.js b/ambari-web/test/installer/step10_test.js
index 055fd70..74ef864 100644
--- a/ambari-web/test/installer/step10_test.js
+++ b/ambari-web/test/installer/step10_test.js
@@ -21,9 +21,362 @@
 var App = require('app');
 require('controllers/wizard/step10_controller');
 
+var controller;
 
 describe('App.WizardStep10Controller', function () {
-  var controller = App.WizardStep10Controller.create();
+
+  beforeEach(function() {
+    controller = App.WizardStep10Controller.create();
+    controller.set('content', {cluster: {status: 'INSTALL COMPLETE'}});
+  });
+
+  afterEach(function() {
+    controller.clearStep();
+  });
+
+  describe('#clearStep', function() {
+    it('should clear clusterInfo', function() {
+      controller.get('clusterInfo').pushObject({});
+      controller.clearStep();
+      expect(controller.get('clusterInfo.length')).to.equal(0);
+    });
+  });
+
+  describe('#loadStep', function() {
+    beforeEach(function() {
+      sinon.spy(controller, 'clearStep');
+      sinon.stub(controller, 'loadRegisteredHosts', Em.K);
+      sinon.stub(controller, 'loadInstalledHosts', Em.K);
+      sinon.stub(controller, 'loadInstallTime', Em.K);
+    });
+    afterEach(function() {
+      controller.clearStep.restore();
+      controller.loadRegisteredHosts.restore();
+      controller.loadInstalledHosts.restore();
+      controller.loadInstallTime.restore();
+    });
+    it('should call clearStep', function() {
+      controller.loadStep();
+      expect(controller.clearStep.calledOnce).to.equal(true);
+    });
+    it('should call loadInstalledHosts', function() {
+      controller.loadStep();
+      expect(controller.loadInstalledHosts.calledOnce).to.equal(true);
+    });
+    it('should loadInstallTime if not installerController', function() {
+      controller.set('content.controllerName', 'addServiceController');
+      controller.loadStep();
+      expect(controller.loadInstallTime.calledOnce).to.equal(true);
+    });
+    var testsForLoadInstallTime = Em.A([
+      {
+        loadMasterComponents: true,
+        loadStartedServices: true,
+        e: true
+      },
+      {
+        loadMasterComponents: true,
+        loadStartedServices: false,
+        e: false
+      },
+      {
+        loadMasterComponents: false,
+        loadStartedServices: false,
+        e: false
+      },
+      {
+        loadMasterComponents: false,
+        loadStartedServices: false,
+        e: false
+      }
+    ]);
+    testsForLoadInstallTime.forEach(function(test) {
+      it('loadMasterComponents: ' + test.loadMasterComponents.toString() + ' loadStartedServices: ' + test.loadStartedServices.toString(), function() {
+        controller.set('content.controllerName', 'installerController');
+        sinon.stub(controller, 'loadMasterComponents', function() {return test.loadMasterComponents;});
+        sinon.stub(controller, 'loadStartedServices', function() {return test.loadStartedServices;});
+        controller.loadStep();
+        expect(controller.loadInstallTime.called).to.equal(test.e);
+        controller.loadMasterComponents.restore();
+        controller.loadStartedServices.restore();
+      });
+    });
+  });
+
+  describe('#loadInstalledHosts', function() {
+    var tests = Em.A([
+      {
+        hosts: {
+          'h1': Em.Object.create({status: 'success', tasks: []}),
+          'h2': Em.Object.create({status: 'success', tasks: []}),
+          'h3': Em.Object.create({status: 'success', tasks: []})
+        },
+        m: 'all success',
+        e: Em.A([
+          {id: 1, l: 3}
+        ])
+      },
+      {
+        hosts: {
+          'h1': Em.Object.create({status: 'warning', tasks: []}),
+          'h2': Em.Object.create({status: 'failed', tasks: []}),
+          'h3': Em.Object.create({status: 'failed', tasks: []})
+        },
+        m: 'some failed, some warning',
+        e: Em.A([
+          {id: 2, l: 3}
+        ])
+      },
+      {
+        hosts: {
+          'h1': Em.Object.create({status: 'failed', tasks: []}),
+          'h2': Em.Object.create({status: 'success', tasks: []}),
+          'h3': Em.Object.create({status: 'warning', tasks: []})
+        },
+        m: 'sone failed, some success, some warning',
+        e: Em.A([
+          {id: 1, l: 1},
+          {id: 2, l: 2}
+        ])
+      }
+    ]);
+    tests.forEach(function(test) {
+      it(test.m, function() {
+        controller.set('content.hosts', test.hosts);
+        controller.set('clusterInfo', Em.A([Em.Object.create({id: 1, status: []})]));
+        controller.loadInstalledHosts();
+        test.e.forEach(function(ex) {
+          expect(controller.get('clusterInfo').findProperty('id', 1).get('status').findProperty('id', ex.id).get('displayStatement').contains(ex.l)).to.equal(true);
+        });
+      })
+    });
+    var testsForFailedTasks = Em.A([
+      {
+        hosts: {
+          'h1': Em.Object.create({
+            status: 'failed',
+            tasks: [
+              {Tasks: {status: 'FAILED'}},
+              {Tasks: {status: 'FAILED'}}
+            ]
+          }),
+          'h2': Em.Object.create({
+            status: 'failed',
+            tasks: [
+              {Tasks: {status: 'FAILED'}}
+            ]
+          }),
+          'h3': Em.Object.create({status: 'failed', tasks: []})
+        },
+        m: 'only failed tasks',
+        e: Em.A([
+          {st: 'failed', l: 3}
+        ])
+      },
+      {
+        hosts: {
+          'h1': Em.Object.create({
+            status: 'failed',
+            tasks: [
+              {Tasks: {status: 'TIMEDOUT'}}
+            ]
+          }),
+          'h2': Em.Object.create({
+            status: 'failed',
+            tasks: [
+              {Tasks: {status: 'TIMEDOUT'}}
+            ]
+          }),
+          'h3': Em.Object.create({
+            status: 'failed',
+            tasks: [
+              {Tasks: {status: 'TIMEDOUT'}}
+            ]
+          })
+        },
+        m: 'only timedout tasks',
+        e: Em.A([
+          {st: 'timedout', l: 3}
+        ])
+      },
+      {
+        hosts: {
+          'h1': Em.Object.create({
+            status: 'failed',
+            tasks: []
+          }),
+          'h2': Em.Object.create({
+            status: 'failed',
+            tasks: []
+          }),
+          'h3': Em.Object.create({
+            status: 'failed',
+            tasks: [
+              {Tasks: {status: 'ABORTED'}},
+              {Tasks: {status: 'ABORTED'}},
+              {Tasks: {status: 'ABORTED'}}
+            ]
+          })
+        },
+        m: 'only aborted tasks',
+        e: Em.A([
+          {st: 'aborted', l: 3}
+        ])
+      },
+      {
+        hosts: {
+          'h1': Em.Object.create({
+            status: 'warning',
+            tasks: [
+              {Tasks: {status: 'FAILED'}},
+              {Tasks: {status: 'FAILED'}}
+            ]
+          }),
+          'h2': Em.Object.create({
+            status: 'warning',
+            tasks: [
+              {Tasks: {status: 'FAILED'}}
+            ]
+          }),
+          'h3': Em.Object.create({status: 'warning', tasks: []})
+        },
+        m: 'only failed tasks, warning hosts',
+        e: Em.A([
+          {st: 'failed', l: 3}
+        ])
+      },
+      {
+        hosts: {
+          'h1': Em.Object.create({
+            status: 'warning',
+            tasks: [
+              {Tasks: {status: 'TIMEDOUT'}}
+            ]
+          }),
+          'h2': Em.Object.create({
+            status: 'warning',
+            tasks: [
+              {Tasks: {status: 'TIMEDOUT'}}
+            ]
+          }),
+          'h3': Em.Object.create({
+            status: 'warning',
+            tasks: [
+              {Tasks: {status: 'TIMEDOUT'}}
+            ]
+          })
+        },
+        m: 'only timedout tasks, warning hosts',
+        e: Em.A([
+          {st: 'timedout', l: 3}
+        ])
+      },
+      {
+        hosts: {
+          'h1': Em.Object.create({
+            status: 'warning',
+            tasks: []
+          }),
+          'h2': Em.Object.create({
+            status: 'warning',
+            tasks: []
+          }),
+          'h3': Em.Object.create({
+            status: 'warning',
+            tasks: [
+              {Tasks: {status: 'ABORTED'}},
+              {Tasks: {status: 'ABORTED'}},
+              {Tasks: {status: 'ABORTED'}}
+            ]
+          })
+        },
+        m: 'only aborted tasks, warning hosts',
+        e: Em.A([
+          {st: 'aborted', l: 3}
+        ])
+      }
+    ]);
+    testsForFailedTasks.forEach(function(test) {
+      it(test.m, function() {
+        controller.set('content.hosts', test.hosts);
+        controller.set('clusterInfo', Em.A([Em.Object.create({id: 1, status: []})]));
+        controller.loadInstalledHosts();
+        test.e.forEach(function(ex) {
+          expect(controller.get('clusterInfo').findProperty('id', 1).get('status').findProperty('id', 2).get('statements').mapProperty('status', ex.st).length).to.equal(ex.l);
+        });
+      })
+    });
+  });
+
+  describe('#loadMasterComponent', function() {
+    var tests = Em.A([
+      {
+        component: Em.Object.create({hostName: 'h1'}),
+        e: 1
+      },
+      {
+        component: Em.Object.create({}),
+        e: 0
+      }
+    ]);
+
+    tests.forEach(function(test) {
+      it(test.component.get('hostName') ? 'Has hosNBame' : 'Doesn\'t have hostName', function() {
+        controller.clearStep();
+        controller.get('clusterInfo').pushObject(Em.Object.create({id: 2, status: []}));
+        controller.loadMasterComponent(test.component);
+        expect(controller.get('clusterInfo').findProperty('id', 2).get('status').length).to.equal(test.e);
+      })
+    });
+  });
+
+  describe('#loadStartedServices', function() {
+    var tests = Em.A([
+      {
+        status: 'STARTED',
+        e: {
+          ids: [3, 4],
+          r: true
+        }
+      },
+      {
+        status: 'FAILED',
+        e: {
+          ids: [3],
+          r: false
+        }
+      }
+    ]);
+    tests.forEach(function(test) {
+      it(test.status, function() {
+        controller.set('content', {cluster: {status: test.status}});
+        var r = controller.loadStartedServices();
+        expect(r).to.equal(test.e.r);
+        expect(controller.get('clusterInfo').mapProperty('id')).to.eql(test.e.ids);
+      });
+    });
+  });
+
+  describe('#loadInstallTime', function() {
+    var tests = Em.A([
+      {
+        installTime: 123,
+        e: [5]
+      },
+      {
+        installTime: null,
+        e: []
+      }
+    ]);
+
+    tests.forEach(function(test) {
+      it('Install time' + test.installTime ? ' available' : ' not available', function() {
+        controller.set('content', {cluster: {installTime: test.installTime}});
+        var r = controller.loadInstallTime();
+        expect(controller.get('clusterInfo').mapProperty('id')).to.eql(test.e);
+      });
+    });
+  });
 
   describe('#calculateInstallTime', function () {
     it('from "9.21" to 9 minutes 12 seconds', function () {
@@ -39,6 +392,23 @@ describe('App.WizardStep10Controller', function () {
       expect(controller.calculateInstallTime('0.5')).to.eql({minutes: 0, seconds: 30});
     });
   });
-});
 
+  describe('#loadMasterComponents', function() {
+
+    var components = Em.A(['NAMENODE','SECONDARY_NAMENODE','JOBTRACKER','HISTORYSERVER','RESOURCEMANAGER','HBASE_MASTER','HIVE_SERVER','OOZIE_SERVER','GANGLIA_SERVER','NAGIOS_SERVER']);
+
+    d3.range(1, components.length).forEach(function(i) {
+      d3.range(1, i).forEach(function(j) {
+        var c = components.slice(0, j);
+        it(c.join(', '), function() {
+          var m = c.map(function(component){return {component: component, displayName: component, hostName: 'h1'};});
+          controller.set('content.masterComponentHosts', m);
+          controller.loadMasterComponents();
+          expect(controller.get('clusterInfo').findProperty('id', 2).get('status').length).to.equal(m.length);
+        });
+      });
+    });
+
+  });
 
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/8865d248/ambari-web/test/views/wizard/step10_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/wizard/step10_view_test.js b/ambari-web/test/views/wizard/step10_view_test.js
new file mode 100644
index 0000000..913e255
--- /dev/null
+++ b/ambari-web/test/views/wizard/step10_view_test.js
@@ -0,0 +1,36 @@
+/**
+ * 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/wizard/step10_view');
+var view;
+describe('App.WizardStep10View', function() {
+  beforeEach(function() {
+    view = App.WizardStep10View.create({
+      controller: App.WizardStep10Controller.create()
+    });
+  });
+  describe('didInsertElement', function() {
+    it('should call loadStep', function() {
+      sinon.stub(view.get('controller'), 'loadStep', Em.K);
+      view.didInsertElement();
+      expect(view.get('controller').loadStep.calledOnce).to.equal(true);
+      view.get('controller').loadStep.restore();
+    });
+  });
+});