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 2014/11/07 12:15:11 UTC

ambari git commit: AMBARI-8198 Unit tests for host page controllers. (atkach)

Repository: ambari
Updated Branches:
  refs/heads/trunk 5b69bea27 -> eaddabf26


AMBARI-8198 Unit tests for host page controllers. (atkach)


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

Branch: refs/heads/trunk
Commit: eaddabf2666ecfc5f8e50508986dfcd0ee4804ea
Parents: 5b69bea
Author: Andrii Tkach <at...@hortonworks.com>
Authored: Fri Nov 7 13:14:50 2014 +0200
Committer: Andrii Tkach <at...@hortonworks.com>
Committed: Fri Nov 7 13:14:50 2014 +0200

----------------------------------------------------------------------
 .../app/controllers/main/host/add_controller.js |  14 +-
 .../controllers/main/host/configs_service.js    |   2 +-
 .../dashboard/config_history_controller_test.js |   2 +
 .../main/host/add_controller_test.js            | 944 ++++++++++++++++++-
 .../main/host/configs_service_test.js           |  40 +
 .../test/controllers/wizard/step3_test.js       | 255 ++---
 6 files changed, 1126 insertions(+), 131 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/eaddabf2/ambari-web/app/controllers/main/host/add_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host/add_controller.js b/ambari-web/app/controllers/main/host/add_controller.js
index d290604..001175a 100644
--- a/ambari-web/app/controllers/main/host/add_controller.js
+++ b/ambari-web/app/controllers/main/host/add_controller.js
@@ -109,23 +109,23 @@ App.AddHostController = App.WizardController.extend({
         selectedServices: [],
         installedServices: []
       };
-      App.StackService.find().forEach(function(item){
-        var isInstalled = App.Service.find().someProperty('id', item.get('serviceName'));
+      App.StackService.find().forEach(function (item) {
+        var isInstalled = App.Service.find().someProperty('serviceName', item.get('serviceName'));
         item.set('isSelected', isInstalled);
         item.set('isInstalled', isInstalled);
         if (isInstalled) {
           services.selectedServices.push(item.get('serviceName'));
           services.installedServices.push(item.get('serviceName'));
         }
-      },this);
-      this.setDBProperty('services',services);
+      }, this);
+      this.setDBProperty('services', services);
     } else {
-      App.StackService.find().forEach(function(item) {
-        var isSelected =   services.selectedServices.contains(item.get('serviceName'));
+      App.StackService.find().forEach(function (item) {
+        var isSelected = services.selectedServices.contains(item.get('serviceName'));
         var isInstalled = services.installedServices.contains(item.get('serviceName'));
         item.set('isSelected', isSelected);
         item.set('isInstalled', isInstalled);
-      },this);
+      }, this);
     }
     this.set('content.services', App.StackService.find());
   },

http://git-wip-us.apache.org/repos/asf/ambari/blob/eaddabf2/ambari-web/app/controllers/main/host/configs_service.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host/configs_service.js b/ambari-web/app/controllers/main/host/configs_service.js
index 14b16d2..9c3c700 100644
--- a/ambari-web/app/controllers/main/host/configs_service.js
+++ b/ambari-web/app/controllers/main/host/configs_service.js
@@ -72,6 +72,6 @@ App.MainHostServiceConfigsController = App.MainServiceInfoConfigsController.exte
     var self = this;
     App.config.launchSwitchConfigGroupOfHostDialog(this.get('selectedConfigGroup'), this.get('configGroups'), this.get('host.hostName'), function (newGroup) {
       self.set('selectedConfigGroup', newGroup);
-    })
+    });
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/eaddabf2/ambari-web/test/controllers/main/dashboard/config_history_controller_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/dashboard/config_history_controller_test.js b/ambari-web/test/controllers/main/dashboard/config_history_controller_test.js
index f83867b..a33175c 100644
--- a/ambari-web/test/controllers/main/dashboard/config_history_controller_test.js
+++ b/ambari-web/test/controllers/main/dashboard/config_history_controller_test.js
@@ -38,11 +38,13 @@ describe('MainConfigHistoryController', function () {
   describe('#load()', function () {
     it('', function () {
       sinon.stub(controller, 'updateTotalCounter', Em.K);
+      sinon.stub(controller, 'loadConfigVersionsToModel').returns({done: Em.K});
 
       controller.load();
       expect(controller.updateTotalCounter.calledOnce).to.be.true;
 
       controller.updateTotalCounter.restore();
+      controller.loadConfigVersionsToModel.restore();
     });
   });
   describe('#loadConfigVersionsToModel()', function () {

http://git-wip-us.apache.org/repos/asf/ambari/blob/eaddabf2/ambari-web/test/controllers/main/host/add_controller_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/host/add_controller_test.js b/ambari-web/test/controllers/main/host/add_controller_test.js
index 284070f..6bd098f 100644
--- a/ambari-web/test/controllers/main/host/add_controller_test.js
+++ b/ambari-web/test/controllers/main/host/add_controller_test.js
@@ -37,13 +37,6 @@ describe('App.AddHostController', function () {
     }
   });
 
-  beforeEach(function () {
-    sinon.spy(controller, "setDBProperty");
-  });
-  afterEach(function () {
-    controller.setDBProperty.restore();
-  });
-
   describe('#removeHosts()', function () {
     var testCases = [
       {
@@ -91,6 +84,12 @@ describe('App.AddHostController', function () {
         result: {}
       }
     ];
+    beforeEach(function () {
+      sinon.spy(controller, "setDBProperty");
+    });
+    afterEach(function () {
+      controller.setDBProperty.restore();
+    });
     testCases.forEach(function (test) {
       it(test.title, function () {
         controller.set('testDBHosts', test.content.dbHosts);
@@ -380,5 +379,934 @@ describe('App.AddHostController', function () {
     it("generatel list of clients to install", function () {
       expect(controller.getClientsToInstall(services, components)).to.eql(clients);
     })
-  })
+  });
+
+  describe("#setCurrentStep()", function () {
+    before(function () {
+      sinon.stub(App.clusterStatus, 'setClusterStatus', Em.K);
+      sinon.stub(App.db, 'setWizardCurrentStep', Em.K);
+    });
+    after(function () {
+      App.clusterStatus.setClusterStatus.restore();
+      App.db.setWizardCurrentStep.restore();
+    });
+    it("call App.clusterStatus.setClusterStatus()", function () {
+      controller.setCurrentStep();
+      expect(App.clusterStatus.setClusterStatus.getCall(0).args[0].wizardControllerName).to.be.equal('addHostController');
+    });
+  });
+
+  describe("#getCluster()", function () {
+    before(function () {
+      sinon.stub(App.router, 'getClusterName').returns('c1');
+    });
+    after(function () {
+      App.router.getClusterName.restore();
+    });
+    it("", function () {
+      controller.set('clusterStatusTemplate', {'prop': 'clusterStatusTemplate'});
+      expect(controller.getCluster()).to.be.eql({
+        prop: 'clusterStatusTemplate',
+        name: 'c1'
+      });
+    });
+  });
+
+  describe("#getInstallOptions()", function () {
+    it("", function () {
+      controller.set('installOptionsTemplate', {'prop': 'installOptionsTemplate'});
+      expect(controller.getInstallOptions()).to.be.eql({
+        prop: 'installOptionsTemplate'
+      });
+    });
+  });
+
+  describe("#loadServices", function () {
+    var services = {
+      db: null,
+      stack: [],
+      model: []
+    };
+    beforeEach(function () {
+      sinon.stub(controller, 'getDBProperty', function () {
+        return services.db;
+      });
+      sinon.stub(App.StackService, 'find', function () {
+        return services.stack;
+      });
+      sinon.stub(App.Service, 'find', function () {
+        return services.model;
+      });
+      sinon.stub(controller, 'setDBProperty', Em.K);
+    });
+    afterEach(function () {
+      controller.getDBProperty.restore();
+      App.StackService.find.restore();
+      App.Service.find.restore();
+      controller.setDBProperty.restore();
+    });
+    it("No services in db, no installed services", function () {
+      services.stack = [Em.Object.create({
+        serviceName: 'S1'
+      })];
+      controller.loadServices();
+      expect(controller.setDBProperty.getCall(0).args).to.eql(['services',
+        {
+          selectedServices: [],
+          installedServices: []
+        }
+      ]);
+      expect(controller.get('content.services')).to.eql([
+        Em.Object.create({
+          serviceName: 'S1',
+          isInstalled: false,
+          isSelected: false
+        })
+      ])
+    });
+    it("No services in db, installed service present", function () {
+      services.stack = [
+        Em.Object.create({
+          serviceName: 'S1'
+        }),
+        Em.Object.create({
+          serviceName: 'S2'
+        })
+      ];
+      services.model = [
+        Em.Object.create({
+          serviceName: 'S1'
+        })
+      ];
+      controller.loadServices();
+      expect(controller.setDBProperty.getCall(0).args).to.eql(['services',
+        {
+          selectedServices: ['S1'],
+          installedServices: ['S1']
+        }
+      ]);
+      expect(controller.get('content.services')).to.eql([
+        Em.Object.create({
+          serviceName: 'S1',
+          isInstalled: true,
+          isSelected: true
+        }),
+        Em.Object.create({
+          serviceName: 'S2',
+          isInstalled: false,
+          isSelected: false
+        })
+      ]);
+    });
+    it("DB is empty", function () {
+      services.stack = [Em.Object.create({
+        serviceName: 'S1'
+      })];
+      services.db = {
+        selectedServices: [],
+        installedServices: []
+      };
+      controller.loadServices();
+      expect(controller.setDBProperty.called).to.be.false;
+      expect(controller.get('content.services')).to.eql([
+        Em.Object.create({
+          serviceName: 'S1',
+          isSelected: false,
+          isInstalled: false
+        })
+      ]);
+    });
+    it("DB has selected and installed services", function () {
+      services.stack = [
+        Em.Object.create({
+          serviceName: 'S1'
+        }),
+        Em.Object.create({
+          serviceName: 'S2'
+        })
+      ];
+      services.db = {
+        selectedServices: ['S1'],
+        installedServices: ['S2']
+      };
+      controller.loadServices();
+      expect(controller.setDBProperty.called).to.be.false;
+      expect(controller.get('content.services')).to.eql([
+        Em.Object.create({
+          serviceName: 'S1',
+          isInstalled: false,
+          isSelected: true
+        }),
+        Em.Object.create({
+          serviceName: 'S2',
+          isInstalled: true,
+          isSelected: false
+        })
+      ]);
+    });
+  });
+
+  describe("#loadSlaveComponentHosts()", function () {
+    var mock = {
+      hosts: null,
+      slaveComponentHosts: null
+    };
+    beforeEach(function () {
+      sinon.stub(controller, 'getDBProperty', function (arg) {
+        if (arg === 'hosts') return mock.hosts;
+        if (arg === 'slaveComponentHosts') return mock.slaveComponentHosts;
+      });
+    });
+    afterEach(function () {
+      controller.getDBProperty.restore();
+    });
+
+    it("No slaveComponentHosts in db, null", function () {
+      controller.loadSlaveComponentHosts();
+      expect(controller.get('content.slaveComponentHosts')).to.be.empty;
+    });
+    it("No slaveComponentHosts in db", function () {
+      mock.slaveComponentHosts = [];
+      controller.loadSlaveComponentHosts();
+      expect(controller.get('content.slaveComponentHosts')).to.be.empty;
+    });
+    it("One slaveComponent without hosts", function () {
+      mock.slaveComponentHosts = [
+        {hosts: []}
+      ];
+      mock.hosts = {};
+      controller.loadSlaveComponentHosts();
+      expect(controller.get('content.slaveComponentHosts')).to.be.eql([
+        {hosts: []}
+      ]);
+    });
+    it("One slaveComponent with host", function () {
+      mock.slaveComponentHosts = [
+        {hosts: [
+          {host_id: 1}
+        ]}
+      ];
+      mock.hosts = {'host1': {id: 1}};
+      controller.loadSlaveComponentHosts();
+      expect(controller.get('content.slaveComponentHosts')).to.be.eql([
+        {hosts: [
+          {
+            host_id: 1,
+            hostName: 'host1'
+          }
+        ]}
+      ]);
+    });
+  });
+
+  describe("#saveClients()", function () {
+    before(function () {
+      sinon.stub(App.StackServiceComponent, 'find').returns('StackServiceComponent');
+      sinon.stub(controller, 'getClientsToInstall').returns(['client']);
+      sinon.stub(controller, 'setDBProperty', Em.K);
+    });
+    after(function () {
+      controller.setDBProperty.restore();
+      App.StackServiceComponent.find.restore();
+      controller.getClientsToInstall.restore();
+    });
+    it("", function () {
+      controller.set('content.services', [Em.Object.create({'isSelected': true})]);
+      controller.saveClients();
+      expect(controller.getClientsToInstall.calledWith(
+        [Em.Object.create({'isSelected': true})],
+        'StackServiceComponent'
+      )).to.be.true;
+      expect(controller.setDBProperty.calledWith('clientInfo', ['client'])).to.be.true;
+      expect(controller.get('content.clients')).to.be.eql(['client']);
+    });
+  });
+
+  describe("#getClientsToInstall()", function () {
+    var testCases = [
+      {
+        title: 'No services',
+        data: {
+          services: [],
+          components: []
+        },
+        result: []
+      },
+      {
+        title: 'No components',
+        data: {
+          services: [
+            {}
+          ],
+          components: []
+        },
+        result: []
+      },
+      {
+        title: 'Component is not client',
+        data: {
+          services: [Em.Object.create({serviceName: 'S1'})],
+          components: [Em.Object.create({serviceName: 'S1'})]
+        },
+        result: []
+      },
+      {
+        title: 'Component is not client',
+        data: {
+          services: [Em.Object.create({serviceName: 'S1'})],
+          components: [Em.Object.create({serviceName: 'S1', isClient: false})]
+        },
+        result: []
+      },
+      {
+        title: 'Component is client',
+        data: {
+          services: [Em.Object.create({serviceName: 'S1'})],
+          components: [Em.Object.create({
+            serviceName: 'S1',
+            isClient: true,
+            componentName: 'C1',
+            displayName: 'C1'
+          })]
+        },
+        result: [
+          {
+            component_name: 'C1',
+            display_name: 'C1',
+            isInstalled: false
+          }
+        ]
+      }
+    ];
+
+    testCases.forEach(function (test) {
+      it(test.title, function () {
+        expect(controller.getClientsToInstall(test.data.services, test.data.components)).to.eql(test.result);
+      });
+    });
+  });
+
+  describe("#applyConfigGroup()", function () {
+    beforeEach(function () {
+      sinon.stub(App.ajax, 'send', Em.K);
+    });
+    afterEach(function () {
+      App.ajax.send.restore();
+    });
+    it("No config groups", function () {
+      controller.set('content.configGroups', []);
+      controller.applyConfigGroup();
+      expect(App.ajax.send.called).to.be.false;
+    });
+    it("selectedConfigGroup absent", function () {
+      controller.set('content.configGroups', [
+        {
+          configGroups: [],
+          selectedConfigGroup: ''
+        }
+      ]);
+      controller.applyConfigGroup();
+      expect(App.ajax.send.called).to.be.false;
+    });
+    it("selectedConfigGroup present", function () {
+      controller.set('content.configGroups', [
+        {
+          configGroups: [
+            {
+              ConfigGroup: {
+                id: 1,
+                group_name: 'G1',
+                hosts: []
+              }
+            }
+          ],
+          selectedConfigGroup: 'G1',
+          hosts: ['host1']
+        }
+      ]);
+      controller.applyConfigGroup();
+
+      expect(App.ajax.send.getCall(0).args[0].name).to.equal('config_groups.update_config_group');
+      expect(App.ajax.send.getCall(0).args[0].data).to.eql({
+        "id": 1,
+        "configGroup": {
+          "ConfigGroup": {
+            "id": 1,
+            "group_name": "G1",
+            "hosts": [
+              {
+                "host_name": "host1"
+              }
+            ]
+          }
+        }
+      });
+    });
+  });
+
+  describe("#getServiceConfigGroups()", function () {
+    before(function () {
+      sinon.stub(controller, 'getDBProperty').withArgs('serviceConfigGroups').returns(['serviceConfigGroup']);
+    });
+    after(function () {
+      controller.getDBProperty.restore();
+    });
+    it("", function () {
+      controller.getServiceConfigGroups();
+      expect(controller.get('content.configGroups')).to.eql(['serviceConfigGroup']);
+    });
+  });
+
+  describe("#saveServiceConfigGroups()", function () {
+    before(function () {
+      sinon.stub(controller, 'setDBProperty', Em.K);
+    });
+    after(function () {
+      controller.setDBProperty.restore();
+    });
+    it("call setDBProperty()", function () {
+      controller.set('content.configGroups', [
+        {}
+      ]);
+      controller.saveServiceConfigGroups();
+      expect(controller.setDBProperty.calledWith('serviceConfigGroups', [
+        {}
+      ])).to.be.true;
+    });
+  });
+
+  describe("#loadServiceConfigGroups()", function () {
+    before(function () {
+      sinon.stub(controller, 'loadServiceConfigGroupsBySlaves', Em.K);
+      sinon.stub(controller, 'loadServiceConfigGroupsByClients', Em.K);
+      sinon.stub(controller, 'sortServiceConfigGroups', Em.K);
+    });
+    after(function () {
+      controller.loadServiceConfigGroupsBySlaves.restore();
+      controller.loadServiceConfigGroupsByClients.restore();
+      controller.sortServiceConfigGroups.restore();
+    });
+    it("", function () {
+      controller.loadServiceConfigGroups();
+      expect(controller.loadServiceConfigGroupsByClients.calledWith([])).to.be.true;
+      expect(controller.loadServiceConfigGroupsBySlaves.calledWith([])).to.be.true;
+      expect(controller.sortServiceConfigGroups.calledWith([])).to.be.true;
+      expect(controller.get('content.configGroups')).to.eql([]);
+    });
+  });
+
+  describe("#sortServiceConfigGroups", function () {
+    var testCases = [
+      {
+        title: 'sorted',
+        selectedServices: [
+          {
+            configGroups: [
+              {
+                ConfigGroup: {
+                  group_name: 'a'
+                }
+              },
+              {
+                ConfigGroup: {
+                  group_name: 'b'
+                }
+              }
+            ]
+          }
+        ],
+        result: ['a', 'b']
+      },
+      {
+        title: 'not sorted',
+        selectedServices: [
+          {
+            configGroups: [
+              {
+                ConfigGroup: {
+                  group_name: 'b'
+                }
+              },
+              {
+                ConfigGroup: {
+                  group_name: 'a'
+                }
+              }
+            ]
+          }
+        ],
+        result: ['a', 'b']
+      },
+      {
+        title: 'sort equal',
+        selectedServices: [
+          {
+            configGroups: [
+              {
+                ConfigGroup: {
+                  group_name: 'a'
+                }
+              },
+              {
+                ConfigGroup: {
+                  group_name: 'a'
+                }
+              }
+            ]
+          }
+        ],
+        result: ['a', 'a']
+      }
+    ];
+    testCases.forEach(function (test) {
+      it(test.title, function () {
+        controller.sortServiceConfigGroups(test.selectedServices);
+        expect(test.selectedServices[0].configGroups.mapProperty('ConfigGroup.group_name')).to.eql(test.result);
+      });
+    });
+  });
+
+  describe("#loadServiceConfigGroupsBySlaves()", function () {
+    beforeEach(function () {
+      sinon.stub(App.StackServiceComponent, 'find').returns(Em.Object.create({
+        stackService: Em.Object.create({
+          serviceName: 'S1',
+          displayName: 's1'
+        })
+      }));
+      controller.set('content.configGroups', [
+        {
+          ConfigGroup: {
+            tag: 'S1',
+            group_name: 'G1'
+          }
+        }
+      ]);
+    });
+    afterEach(function () {
+      App.StackServiceComponent.find.restore();
+    });
+    it("slaveComponentHosts is empty", function () {
+      var selectedServices = [];
+      controller.set('content.slaveComponentHosts', []);
+      expect(controller.loadServiceConfigGroupsBySlaves(selectedServices)).to.be.false;
+      expect(selectedServices).to.be.empty;
+    });
+    it("slaveComponentHosts has ho hosts", function () {
+      var selectedServices = [];
+      controller.set('content.slaveComponentHosts', [
+        {hosts: []}
+      ]);
+      expect(controller.loadServiceConfigGroupsBySlaves(selectedServices)).to.be.true;
+      expect(selectedServices).to.be.empty;
+    });
+    it("slaveComponentHosts is CLIENT", function () {
+      var selectedServices = [];
+      controller.set('content.slaveComponentHosts', [
+        {
+          hosts: [
+            {hostName: 'host1'}
+          ],
+          componentName: 'CLIENT'
+        }
+      ]);
+      expect(controller.loadServiceConfigGroupsBySlaves(selectedServices)).to.be.true;
+      expect(selectedServices).to.be.empty;
+    });
+    it("slaveComponentHosts is slave", function () {
+      var selectedServices = [];
+      controller.set('content.slaveComponentHosts', [
+        {
+          hosts: [
+            {hostName: 'host1'}
+          ],
+          componentName: 'C1'
+        }
+      ]);
+      expect(controller.loadServiceConfigGroupsBySlaves(selectedServices)).to.be.true;
+      expect(selectedServices).to.eql([
+        {
+          "serviceId": "S1",
+          "displayName": "s1",
+          "hosts": [
+            "host1"
+          ],
+          "configGroupsNames": [
+            "s1 Default",
+            "G1"
+          ],
+          "configGroups": [
+            {
+              "ConfigGroup": {
+                "tag": "S1",
+                "group_name": "G1"
+              }
+            }
+          ],
+          "selectedConfigGroup": "s1 Default"
+        }
+      ]);
+    });
+  });
+
+  describe("#loadServiceConfigGroupsByClients()", function () {
+    beforeEach(function () {
+      sinon.stub(App.StackServiceComponent, 'find').returns(Em.Object.create({
+        stackService: Em.Object.create({
+          serviceName: 'S1',
+          displayName: 's1'
+        })
+      }));
+      sinon.stub(controller, 'loadClients', Em.K);
+      controller.set('content.configGroups', [
+        {
+          ConfigGroup: {
+            tag: 'S1',
+            group_name: 'G1'
+          }
+        }
+      ]);
+    });
+    afterEach(function () {
+      controller.loadClients.restore();
+      App.StackServiceComponent.find.restore();
+    });
+    it("Clients is null", function () {
+      var selectedServices = [];
+      controller.set('content.slaveComponentHosts', null);
+      controller.set('content.clients', null);
+
+      expect(controller.loadServiceConfigGroupsByClients(selectedServices)).to.be.false;
+      expect(selectedServices).to.be.empty;
+    });
+    it("No CLIENT component", function () {
+      var selectedServices = [];
+      controller.set('content.slaveComponentHosts', []);
+      controller.set('content.clients', []);
+
+      expect(controller.loadServiceConfigGroupsByClients(selectedServices)).to.be.false;
+      expect(selectedServices).to.be.empty;
+    });
+    it("Clients is empty", function () {
+      var selectedServices = [];
+      controller.set('content.slaveComponentHosts', [
+        {
+          componentName: 'CLIENT',
+          hosts: []
+        }
+      ]);
+      controller.set('content.clients', []);
+
+      expect(controller.loadServiceConfigGroupsByClients(selectedServices)).to.be.false;
+      expect(selectedServices).to.be.empty;
+    });
+    it("Client component does not have hosts", function () {
+      var selectedServices = [];
+      controller.set('content.slaveComponentHosts', [
+        {
+          componentName: 'CLIENT',
+          hosts: []
+        }
+      ]);
+      controller.set('content.clients', [
+        {}
+      ]);
+
+      expect(controller.loadServiceConfigGroupsByClients(selectedServices)).to.be.false;
+      expect(selectedServices).to.be.empty;
+    });
+    it("Client present, selectedServices is empty", function () {
+      var selectedServices = [];
+      controller.set('content.slaveComponentHosts', [
+        {
+          componentName: 'CLIENT',
+          hosts: [
+            {hostName: 'host1'}
+          ]
+        }
+      ]);
+      controller.set('content.clients', [
+        {
+          component_name: 'C1'
+        }
+      ]);
+
+      expect(controller.loadServiceConfigGroupsByClients(selectedServices)).to.be.true;
+      expect(selectedServices).to.be.eql([
+        {
+          "serviceId": "S1",
+          "displayName": "s1",
+          "hosts": [
+            "host1"
+          ],
+          "configGroupsNames": [
+            "s1 Default",
+            "G1"
+          ],
+          "configGroups": [
+            {
+              "ConfigGroup": {
+                "tag": "S1",
+                "group_name": "G1"
+              }
+            }
+          ],
+          "selectedConfigGroup": "s1 Default"
+        }
+      ]);
+    });
+    it("Client present, selectedServices has service", function () {
+      var selectedServices = [
+        {
+          serviceId: 'S1',
+          hosts: ['host1', 'host2']
+        }
+      ];
+      controller.set('content.slaveComponentHosts', [
+        {
+          componentName: 'CLIENT',
+          hosts: [
+            {hostName: 'host1'}
+          ]
+        }
+      ]);
+      controller.set('content.clients', [
+        {
+          component_name: 'C1'
+        }
+      ]);
+
+      expect(controller.loadServiceConfigGroupsByClients(selectedServices)).to.be.true;
+      expect(selectedServices[0].hosts).to.be.eql(["host1", "host2"]);
+    });
+  });
+
+  describe("#loadServiceConfigProperties()", function () {
+    beforeEach(function () {
+      this.mock = sinon.stub(App.db, 'get');
+      this.mock.withArgs('Installer', 'serviceConfigProperties').returns([1]);
+    });
+    afterEach(function () {
+      this.mock.restore();
+    });
+    it("serviceConfigProperties is null", function () {
+      this.mock.withArgs('AddService', 'serviceConfigProperties').returns(null);
+      controller.loadServiceConfigProperties();
+      expect(controller.get('content.serviceConfigProperties')).to.eql([1]);
+    });
+    it("serviceConfigProperties is empty", function () {
+      this.mock.withArgs('AddService', 'serviceConfigProperties').returns([]);
+      controller.loadServiceConfigProperties();
+      expect(controller.get('content.serviceConfigProperties')).to.eql([1]);
+    });
+    it("serviceConfigProperties has data", function () {
+      this.mock.withArgs('AddService', 'serviceConfigProperties').returns([1]);
+      controller.loadServiceConfigProperties();
+      expect(controller.get('content.serviceConfigProperties')).to.eql([1]);
+    });
+  });
+
+  describe("#loadAllPriorSteps()", function () {
+    var stepsSet = {
+      '1': [
+        {
+          name: 'load',
+          args: ['hosts']
+        },
+        {
+          name: 'load',
+          args: ['installOptions']
+        },
+        {
+          name: 'load',
+          args: ['cluster']
+        }
+      ],
+      '2': [
+        {
+          name: 'loadServices',
+          args: []
+        }
+      ],
+      '3': [
+        {
+          name: 'loadClients',
+          args: []
+        },
+        {
+          name: 'loadServices',
+          args: []
+        },
+        {
+          name: 'loadMasterComponentHosts',
+          args: []
+        },
+        {
+          name: 'loadSlaveComponentHosts',
+          args: []
+        },
+        {
+          name: 'load',
+          args: ['hosts']
+        }
+      ],
+      '5': [
+        {
+          name: 'loadServiceConfigProperties',
+          args: []
+        },
+        {
+          name: 'getServiceConfigGroups',
+          args: []
+        }
+      ]
+    };
+    var testCases = [
+      {
+        currentStep: '0',
+        calledFunctions: []
+      },
+      {
+        currentStep: '1',
+        calledFunctions: stepsSet['1']
+      },
+      {
+        currentStep: '2',
+        calledFunctions: stepsSet['1'].concat(stepsSet['2'])
+      },
+      {
+        currentStep: '3',
+        calledFunctions: stepsSet['3'].concat(stepsSet['2'], stepsSet['1'])
+      },
+      {
+        currentStep: '4',
+        calledFunctions: stepsSet['3'].concat(stepsSet['2'], stepsSet['1'])
+      },
+      {
+        currentStep: '5',
+        calledFunctions: stepsSet['5'].concat(stepsSet['3'], stepsSet['2'], stepsSet[1])
+      },
+      {
+        currentStep: '6',
+        calledFunctions: stepsSet['5'].concat(stepsSet['3'], stepsSet['2'], stepsSet[1])
+      },
+      {
+        currentStep: '7',
+        calledFunctions: stepsSet['5'].concat(stepsSet['3'], stepsSet['2'], stepsSet[1])
+      },
+      {
+        currentStep: '8',
+        calledFunctions: []
+      }
+    ];
+    var functionsToCall = [
+      'loadServiceConfigProperties',
+      'getServiceConfigGroups',
+      'loadClients',
+      'loadServices',
+      'loadMasterComponentHosts',
+      'loadSlaveComponentHosts',
+      'load'
+    ];
+    beforeEach(function () {
+      this.mock = sinon.stub(controller, 'get');
+      sinon.stub(controller, 'loadServiceConfigProperties', Em.K);
+      sinon.stub(controller, 'getServiceConfigGroups', Em.K);
+      sinon.stub(controller, 'loadClients', Em.K);
+      sinon.stub(controller, 'loadServices', Em.K);
+      sinon.stub(controller, 'loadMasterComponentHosts', Em.K);
+      sinon.stub(controller, 'loadSlaveComponentHosts', Em.K);
+      sinon.stub(controller, 'load', Em.K);
+    });
+    afterEach(function () {
+      this.mock.restore();
+      controller.loadServiceConfigProperties.restore();
+      controller.getServiceConfigGroups.restore();
+      controller.loadClients.restore();
+      controller.loadServices.restore();
+      controller.loadMasterComponentHosts.restore();
+      controller.loadSlaveComponentHosts.restore();
+      controller.load.restore();
+    });
+    testCases.forEach(function (test) {
+      it("current step - " + test.currentStep, function () {
+        this.mock.returns(test.currentStep);
+        controller.loadAllPriorSteps();
+        functionsToCall.forEach(function (fName) {
+          var callStack = test.calledFunctions.filterProperty('name', fName);
+          if (callStack.length > 0) {
+            callStack.forEach(function (f, index) {
+              expect(controller[f.name].getCall(index).args).to.eql(f.args);
+            }, this);
+          } else {
+            expect(controller[fName].called).to.be.false;
+          }
+        }, this);
+      });
+    }, this);
+  });
+
+  describe("#clearAllSteps()", function () {
+    beforeEach(function () {
+      sinon.stub(controller, 'clearInstallOptions', Em.K);
+      sinon.stub(controller, 'getCluster').returns({});
+    });
+    afterEach(function () {
+      controller.clearInstallOptions.restore();
+      controller.getCluster.restore();
+    });
+    it("", function () {
+      controller.clearAllSteps();
+      expect(controller.getCluster.calledOnce).to.be.true;
+      expect(controller.clearInstallOptions.calledOnce).to.be.true;
+      expect(controller.get('content.cluster')).to.eql({});
+    });
+  });
+
+  describe("#clearStorageData()", function () {
+    beforeEach(function () {
+      sinon.stub(controller, 'resetDbNamespace', Em.K);
+    });
+    afterEach(function () {
+      controller.resetDbNamespace.restore();
+    });
+    it("launch resetDbNamespace", function () {
+      controller.clearStorageData();
+      expect(controller.resetDbNamespace.calledOnce).to.be.true;
+    });
+  });
+
+  describe("#finish()", function () {
+    var mock = {
+      updateAll: Em.K,
+      getAllHostNames: Em.K
+    };
+    beforeEach(function () {
+      sinon.stub(controller, 'setCurrentStep', Em.K);
+      sinon.stub(controller, 'clearAllSteps', Em.K);
+      sinon.stub(controller, 'clearStorageData', Em.K);
+      sinon.stub(App.updater, 'immediateRun', Em.K);
+      sinon.stub(App.router, 'get').returns(mock);
+      sinon.spy(mock, 'updateAll');
+      sinon.spy(mock, 'getAllHostNames');
+    });
+    afterEach(function () {
+      controller.setCurrentStep.restore();
+      controller.clearAllSteps.restore();
+      controller.clearStorageData.restore();
+      App.updater.immediateRun.restore();
+      App.router.get.restore();
+      mock.updateAll.restore();
+      mock.getAllHostNames.restore();
+    });
+    it("", function () {
+      controller.finish();
+      expect(controller.setCurrentStep.calledWith('1')).to.be.true;
+      expect(controller.clearAllSteps.calledOnce).to.be.true;
+      expect(controller.clearStorageData.calledOnce).to.be.true;
+      expect(mock.updateAll.calledOnce).to.be.true;
+      expect(App.updater.immediateRun.calledWith('updateHost')).to.be.true;
+      expect(mock.getAllHostNames.calledOnce).to.be.true;
+    });
+  });
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/eaddabf2/ambari-web/test/controllers/main/host/configs_service_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/host/configs_service_test.js b/ambari-web/test/controllers/main/host/configs_service_test.js
index b1e8690..a014e51 100644
--- a/ambari-web/test/controllers/main/host/configs_service_test.js
+++ b/ambari-web/test/controllers/main/host/configs_service_test.js
@@ -100,4 +100,44 @@ describe('App.MainHostServiceConfigsController', function () {
     });
   });
 
+	describe("#loadStep()", function () {
+		it("should set host", function () {
+			controller.set('content', {
+				host: 'host1'
+			});
+			controller.loadStep();
+			expect(controller.get('host')).to.be.equal('host1');
+		});
+	});
+
+	describe("#renderServiceConfigs()", function () {
+		it("should call filterServiceConfigs", function () {
+			var serviceConfigs = {
+				configCategories: 'val'
+			};
+			sinon.stub(controller, 'filterServiceConfigs', function () {
+				this._super = Em.K;
+			});
+			controller.renderServiceConfigs(serviceConfigs);
+
+			expect(controller.filterServiceConfigs.calledWith('val')).to.be.true;
+			controller.filterServiceConfigs.restore();
+		});
+	});
+
+	describe("#switchHostGroup()", function () {
+		it("should call launchSwitchConfigGroupOfHostDialog", function () {
+			sinon.stub(App.config, 'launchSwitchConfigGroupOfHostDialog', Em.K);
+			sinon.stub(controller, 'onConfigGroupChange', Em.K);
+			controller.set('selectedConfigGroup', {});
+			controller.set('configGroups', []);
+			controller.set('host', {hostName: 'host1'});
+			controller.switchHostGroup();
+
+			expect(App.config.launchSwitchConfigGroupOfHostDialog.calledWith({}, [], 'host1')).to.be.true;
+			App.config.launchSwitchConfigGroupOfHostDialog.restore();
+			controller.onConfigGroupChange.restore();
+		});
+	});
+
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/eaddabf2/ambari-web/test/controllers/wizard/step3_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/wizard/step3_test.js b/ambari-web/test/controllers/wizard/step3_test.js
index 76e2e88..d635911 100644
--- a/ambari-web/test/controllers/wizard/step3_test.js
+++ b/ambari-web/test/controllers/wizard/step3_test.js
@@ -26,18 +26,21 @@ require('models/host');
 require('controllers/wizard/step3_controller');
 
 describe('App.WizardStep3Controller', function () {
-
-  beforeEach(function() {
-    c = App.WizardStep3Controller.create({
-      content: Em.Object.create({installedHosts: Em.A([]), installOptions: {}}),
-      wizardController: App.InstallerController.create(),
-      disablePreviousSteps: Em.K
-    });
+  var c = App.WizardStep3Controller.create({
+    content: Em.Object.create({installedHosts: Em.A([]), installOptions: {}}),
+    wizardController: App.InstallerController.create(),
+    disablePreviousSteps: Em.K
+  });
+  beforeEach(function () {
+    sinon.stub(App.db, 'getDisplayLength', Em.K);
+    sinon.stub(App.db, 'getFilterConditions').returns([]);
     sinon.stub(App.router, 'send', Em.K);
   });
 
   afterEach(function() {
+    App.db.getDisplayLength.restore();
     App.router.send.restore();
+    App.db.getFilterConditions.restore();
   });
 
   describe('#getAllRegisteredHostsCallback', function () {
@@ -222,105 +225,76 @@ describe('App.WizardStep3Controller', function () {
   describe('#loadStep', function() {
 
     beforeEach(function() {
-      sinon.stub(App.router, 'get', function(k) {
-        if ('clusterController' === k) {
-          return Em.Object.create({
-            loadAmbariProperties: Em.K
-          });
-        }
-        return Em.get(App.router, k);
+      sinon.stub(App.router, 'get').withArgs('clusterController').returns({
+        loadAmbariProperties: Em.K
       });
+      sinon.spy(c, 'clearStep');
+      sinon.stub(c, 'loadHosts', Em.K);
+      sinon.stub(c, 'disablePreviousSteps', Em.K);
     });
 
     afterEach(function() {
       App.router.get.restore();
+      c.clearStep.restore();
+      c.disablePreviousSteps.restore();
+      c.loadHosts.restore();
     });
 
     it('should set registrationStartedAt to null', function() {
-      c.set('disablePreviousSteps', Em.K);
       c.set('registrationStartedAt', {});
       c.loadStep();
       expect(c.get('registrationStartedAt')).to.be.null;
     });
     it('should call clearStep', function() {
-      c.set('disablePreviousSteps', Em.K);
-      c.set('loadHosts', Em.K);
-      sinon.spy(c, 'clearStep');
       c.loadStep();
       expect(c.get('clearStep').calledOnce).to.equal(true);
-      c.clearStep.restore();
     });
     it('should call loadHosts', function() {
-      c.set('disablePreviousSteps', Em.K);
-      c.set('loadHosts', Em.K);
-      sinon.spy(c, 'loadHosts');
       c.loadStep();
       expect(c.get('loadHosts').calledOnce).to.equal(true);
-      c.loadHosts.restore();
     });
     it('should call disablePreviousSteps', function() {
-      c.set('disablePreviousSteps', Em.K);
-      c.set('loadHosts', Em.K);
-      sinon.spy(c, 'disablePreviousSteps');
       c.loadStep();
       expect(c.get('disablePreviousSteps').calledOnce).to.equal(true);
-      c.disablePreviousSteps.restore();
     });
   });
 
   describe('#loadHosts', function() {
-
+    beforeEach(function(){
+      sinon.stub(c, 'navigateStep');
+    });
     afterEach(function() {
-      App.get.restore();
+      c.navigateStep.restore();
+      App.set('testMode', false);
     });
 
     it('should set isLoaded to true', function() {
-      sinon.stub(App, 'get', function(k) {
-        if ('testMode' === k) return true;
-        return Em.get(App, k);
-      });
-      c.set('navigateStep', Em.K);
+      App.set('testMode', true);
       c.set('content', {hosts: {}});
       c.loadHosts();
       expect(c.get('isLoaded')).to.equal(true);
     });
     it('should set bootStatus REGISTERED on testMode', function() {
-      sinon.stub(App, 'get', function(k) {
-        if ('testMode' === k) return true;
-        return Em.get(App, k);
-      });
-      c.set('navigateStep', Em.K);
+      App.set('testMode', true);
       c.set('content', {hosts: {c: {name: 'name'}}});
       c.loadHosts();
       expect(c.get('hosts').everyProperty('bootStatus', 'REGISTERED')).to.equal(true);
     });
     it('should set bootStatus DONE on "real" mode and when installOptions.manualInstall is selected', function() {
-      sinon.stub(App, 'get', function(k) {
-        if ('testMode' === k) return false;
-        return Em.get(App, k);
-      });
-      c.set('navigateStep', Em.K);
+      App.set('testMode', false);
       c.set('content.installOptions', {manualInstall: true});
       c.set('content.hosts', {c: {name: 'name'}});
       c.loadHosts();
       expect(c.get('hosts').everyProperty('bootStatus', 'DONE')).to.equal(true);
     });
     it('should set bootStatus PENDING on "real" mode and when installOptions.manualInstall is not selected', function() {
-      sinon.stub(App, 'get', function(k) {
-        if ('testMode' === k) return false;
-        return Em.get(App, k);
-      });
-      c.set('navigateStep', Em.K);
+      App.set('testMode', false);
       c.set('content', {installOptions:{manualInstall: false}, hosts: {c: {name: 'name'}}});
       c.loadHosts();
       expect(c.get('hosts').everyProperty('bootStatus', 'PENDING')).to.equal(true);
     });
     it('should set bootStatus PENDING on "real" mode and when installOptions.manualInstall is not selected', function() {
-      sinon.stub(App, 'get', function(k) {
-        if ('testMode' === k) return true;
-        return Em.get(App, k);
-      });
-      c.set('navigateStep', Em.K);
+      App.set('testMode', true);
       c.set('content', {hosts: {c: {name: 'name'}, d: {name: 'name1'}}});
       c.loadHosts();
       expect(c.get('hosts').everyProperty('isChecked', false)).to.equal(true);
@@ -398,12 +372,16 @@ describe('App.WizardStep3Controller', function () {
   });
 
   describe('#removeHosts', function() {
+    beforeEach(function(){
+      sinon.spy(App, 'showConfirmationPopup');
+    });
+    afterEach(function(){
+      App.showConfirmationPopup.restore();
+    });
 
     it('should call App.showConfirmationPopup', function() {
-      sinon.spy(App, 'showConfirmationPopup');
       c.removeHosts(Em.A([]));
       expect(App.showConfirmationPopup.calledOnce).to.equal(true);
-      App.showConfirmationPopup.restore();
     });
     it('primary should disable Submit if no more hosts', function() {
       var hosts = [{}];
@@ -415,26 +393,33 @@ describe('App.WizardStep3Controller', function () {
   });
 
   describe('#removeHost', function() {
+    before(function(){
+      sinon.stub(c, 'removeHosts', Em.K);
+    });
+    after(function(){
+      c.removeHosts.restore();
+    });
     it('should call removeHosts with array as arg', function() {
       var host = {a:''};
-      sinon.spy(c, 'removeHosts');
       c.removeHost(host);
       expect(c.removeHosts.calledWith([host]));
-      c.removeHosts.restore();
     });
   });
 
   describe('#removeSelectedHosts', function() {
+    before(function(){
+      sinon.stub(c, 'removeHosts', Em.K);
+    });
+    after(function(){
+      c.removeHosts.restore();
+    });
     it('should remove selected hosts', function() {
-      c = App.WizardStep3Controller.create({
-        wizardController: App.InstallerController.create(),
-        hosts: [
-          {isChecked: true, name: 'c1'},
-          {isChecked: false, name: 'c2'}
-        ]
-      });
-      c.removeSelectedHosts().onPrimary();
-      expect(c.get('hosts').mapProperty('name')).to.eql(['c2']);
+      c.set('hosts', [
+        {isChecked: true, name: 'c1'},
+        {isChecked: false, name: 'c2'}
+      ]);
+      c.removeSelectedHosts();
+      expect(c.removeHosts.calledWith([{isChecked: true, name: 'c1'}])).to.be.true;
     });
   });
 
@@ -491,76 +476,84 @@ describe('App.WizardStep3Controller', function () {
   });
 
   describe('#retryHost', function() {
-    it('should callretryHosts with array as arg', function() {
-      var host = {n: 'c'}, s = sinon.stub(App.router, 'get', function() {
+    before(function(){
+      sinon.spy(c, 'retryHosts');
+      sinon.stub(App.router, 'get', function() {
         return {launchBootstrap: Em.K}
       });
-      sinon.spy(c, 'retryHosts');
+      sinon.stub(c, 'doBootstrap', Em.K);
+    });
+    after(function(){
+      c.retryHosts.restore();
+      App.router.get.restore();
+      c.doBootstrap.restore();
+    });
+    it('should callretryHosts with array as arg', function() {
+      var host = {n: 'c'};
       c.set('content', {installOptions: {}});
-      c.set('doBootstrap', Em.K);
       c.retryHost(host);
       expect(c.retryHosts.calledWith([host])).to.equal(true);
-      c.retryHosts.restore();
-      s.restore();
     });
   });
 
   describe('#retrySelectedHosts', function() {
+    beforeEach(function () {
+      sinon.spy(c, 'retryHosts');
+      sinon.stub(App.router, 'get', function () {
+        return {launchBootstrap: Em.K}
+      });
+      sinon.stub(c, 'doBootstrap', Em.K);
+    });
+    afterEach(function () {
+      c.retryHosts.restore();
+      App.router.get.restore();
+      c.doBootstrap.restore();
+    });
     it('shouldn\'t do nothing if isRetryDisabled is true', function() {
       c.set('isRetryDisabled', true);
-      sinon.spy(c, 'retryHosts');
       c.retrySelectedHosts();
       expect(c.retryHosts.called).to.equal(false);
-      c.retryHosts.restore();
     });
     it('should retry hosts with FAILED bootStatus and set isRetryDisabled to true', function() {
-      var s = sinon.stub(App.router, 'get', function() {
-        return {launchBootstrap: Em.K}
-      });
-      c = App.WizardStep3Controller.create({
-        wizardController: App.InstallerController.create(),
-        isRetryDisabled: false,
-        bootHosts: Em.A([Em.Object.create({name: 'c1', bootStatus: 'FAILED'}), Em.Object.create({name: 'c2', bootStatus: 'REGISTERED'})]),
-        content: {installOptions: {}},
-        doBootstrap: Em.K
-      });
-      sinon.spy(c, 'retryHosts');
+      c.set('isRetryDisabled', false);
+      c.set('bootHosts', Em.A([Em.Object.create({name: 'c1', bootStatus: 'FAILED'}), Em.Object.create({name: 'c2', bootStatus: 'REGISTERED'})]));
       c.retrySelectedHosts();
       expect(c.retryHosts.calledWith([{name: 'c1', bootStatus: 'RUNNING'}]));
       expect(c.get('isRetryDisabled')).to.equal(true);
-      c.retryHosts.restore();
-      s.restore();
     });
   });
 
   describe('#startBootstrap', function() {
+    beforeEach(function(){
+      sinon.stub(c, 'doBootstrap', Em.K);
+    });
+    afterEach(function(){
+      c.doBootstrap.restore();
+    });
     it('should drop numPolls and registrationStartedAt', function() {
       c.set('numPolls', 123);
       c.set('registrationStartedAt', 1234);
-      c.set('doBootstrap', Em.K);
       c.startBootstrap();
       expect(c.get('numPolls')).to.equal(0);
       expect(c.get('registrationStartedAt')).to.be.null;
     });
     it('should drop numPolls and registrationStartedAt', function() {
-      var hosts = Em.A([{name: 'c1'}, {name: 'c2'}]);
-      c = App.WizardStep3Controller.create({
-        wizardController: App.InstallerController.create(),
-        doBootstrap: Em.K,
-        setRegistrationInProgressOnce: Em.K,
-        hosts: hosts
-      });
+      c.set('hosts', Em.A([{name: 'c1'}, {name: 'c2'}]))
       c.startBootstrap();
       expect(c.get('bootHosts').mapProperty('name')).to.eql(['c1','c2']);
     });
   });
 
   describe('#setRegistrationInProgressOnce', function() {
-    it('should call Ember.run.once with "setRegistrationInProgress"', function() {
+    before(function(){
       sinon.spy(Em.run, 'once');
+    });
+    after(function(){
+      Em.run.once.restore();
+    });
+    it('should call Ember.run.once with "setRegistrationInProgress"', function() {
       c.setRegistrationInProgressOnce();
       expect(Em.run.once.firstCall.args[1]).to.equal('setRegistrationInProgress');
-      Em.run.once.restore();
     });
   });
 
@@ -584,7 +577,7 @@ describe('App.WizardStep3Controller', function () {
           Em.Object.create({bootStatus: 'RUNNING'})
         ],
         isLoaded: true,
-        e: false,
+        e: true,
         m: 'bootHosts without REGISTERED/FAILED and isLoaded is true'
       },
       {
@@ -620,7 +613,7 @@ describe('App.WizardStep3Controller', function () {
           Em.Object.create({bootStatus: 'RUNNING'})
         ],
         isLoaded: true,
-        e: false,
+        e: true,
         m: 'bootHosts with one REGISTERED and isLoaded is true'
       },
       {
@@ -629,24 +622,35 @@ describe('App.WizardStep3Controller', function () {
           Em.Object.create({bootStatus: 'RUNNING'})
         ],
         isLoaded: true,
-        e: false,
+        e: true,
         m: 'bootHosts with one FAILED and isLoaded is true'
       }
     ]);
 
+    beforeEach(function(){
+      sinon.stub(c, 'getAllRegisteredHosts', Em.K);
+      sinon.stub(c, 'disablePreviousSteps', Em.K);
+      sinon.stub(c, 'setRegistrationInProgressOnce', Em.K);
+      sinon.stub(c, 'navigateStep', Em.K);
+    });
+    afterEach(function(){
+      c.disablePreviousSteps.restore();
+      c.getAllRegisteredHosts.restore();
+      c.setRegistrationInProgressOnce.restore();
+      c.navigateStep.restore();
+    });
+
     tests.forEach(function(test) {
       it(test.m, function() {
-        sinon.stub(c, 'disablePreviousSteps', Em.K);
         c.set('bootHosts', test.bootHosts);
         c.set('isLoaded', test.isLoaded);
         c.setRegistrationInProgress();
         expect(c.get('isRegistrationInProgress')).to.equal(test.e);
-        c.disablePreviousSteps.restore();
       });
     });
   });
 
-  describe('#doBootstrap', function() {
+  describe('#doBootstrap()', function() {
     beforeEach(function() {
       sinon.spy(App.ajax, 'send');
     });
@@ -659,15 +663,11 @@ describe('App.WizardStep3Controller', function () {
       expect(App.ajax.send.called).to.equal(false);
     });
     it('should increment numPolls if stopBootstrap is false', function() {
-      c.set('stopBootstrap', false);
       c.set('numPolls', 0);
-      c.doBootstrap();
-      expect(c.get('numPolls')).to.equal(1);
-    });
-    it('should do ajax call if stopBootstrap is false', function() {
       c.set('stopBootstrap', false);
       c.doBootstrap();
-      expect(App.ajax.send.called).to.equal(true);
+      expect(App.ajax.send.calledOnce).to.be.true;
+      expect(c.get('numPolls')).to.equal(1);
     });
   });
 
@@ -716,6 +716,7 @@ describe('App.WizardStep3Controller', function () {
           Em.Object.create({bootStatus: 'DONE'})
         ]),
         data: {items:[]},
+        registrationStartedAt: 1000000,
         m: 'one host DONE',
         e: {
           bs: 'REGISTERING',
@@ -738,7 +739,8 @@ describe('App.WizardStep3Controller', function () {
           Em.Object.create({bootStatus: 'REGISTERING', name: 'c1'})
         ]),
         data: {items:[{Hosts: {host_name: 'c2'}}]},
-        m: 'one host REGISTERING but data without info about it',
+        registrationStartedAt: 0,
+        m: 'one host REGISTERING but data missing info about it, timeout',
         e: {
           bs: 'FAILED',
           getHostInfoCalled: false
@@ -746,6 +748,18 @@ describe('App.WizardStep3Controller', function () {
       },
       {
         bootHosts: Em.A([
+          Em.Object.create({bootStatus: 'REGISTERING', name: 'c1'})
+        ]),
+        data: {items:[{Hosts: {host_name: 'c2'}}]},
+        registrationStartedAt: 1000000,
+        m: 'one host REGISTERING but data missing info about it',
+        e: {
+          bs: 'REGISTERING',
+          getHostInfoCalled: false
+        }
+      },
+      {
+        bootHosts: Em.A([
           Em.Object.create({bootStatus: 'RUNNING', name: 'c1'})
         ]),
         data: {items:[{Hosts: {host_name: 'c1'}}]},
@@ -756,15 +770,22 @@ describe('App.WizardStep3Controller', function () {
         }
       }
     ]);
+    beforeEach(function(){
+      sinon.spy(c, 'getHostInfo');
+      sinon.stub(App, 'dateTime').returns(1000000);
+    });
+    afterEach(function(){
+      c.getHostInfo.restore();
+      App.dateTime.restore();
+    });
     tests.forEach(function(test) {
       it(test.m, function() {
-        sinon.spy(c, 'getHostInfo');
         c.set('content.installedHosts', []);
         c.set('bootHosts', test.bootHosts);
+        c.set('registrationStartedAt', test.registrationStartedAt);
         c.isHostsRegisteredSuccessCallback(test.data);
         expect(c.get('bootHosts')[0].get('bootStatus')).to.equal(test.e.bs);
         expect(c.getHostInfo.called).to.equal(test.e.getHostInfoCalled);
-        c.getHostInfo.restore();
       });
     });
   });
@@ -1468,6 +1489,12 @@ describe('App.WizardStep3Controller', function () {
   });
 
   describe('#navigateStep', function() {
+    beforeEach(function(){
+      sinon.stub(c, 'startBootstrap', Em.K);
+    });
+    afterEach(function(){
+      c.startBootstrap.restore();
+    });
     Em.A([
         {
           isLoaded: true,
@@ -1513,7 +1540,6 @@ describe('App.WizardStep3Controller', function () {
               }
             })
           });
-          sinon.stub(c, 'startBootstrap', Em.K);
           c.navigateStep();
           if(test.e) {
             expect(c.startBootstrap.calledOnce).to.equal(true);
@@ -1521,7 +1547,6 @@ describe('App.WizardStep3Controller', function () {
           else {
             expect(c.startBootstrap.called).to.equal(false);
           }
-          c.startBootstrap.restore();
         });
       });