Explorar el Código

AMBARI-13123 Usability: do not force redirect the user to the currently running wizard if another user logs in. (atkach)

Andrii Tkach hace 10 años
padre
commit
9763e6447a
Se han modificado 28 ficheros con 390 adiciones y 50 borrados
  1. 8 3
      ambari-web/app/app.js
  2. 1 0
      ambari-web/app/assets/test/tests.js
  3. 1 0
      ambari-web/app/controllers.js
  4. 1 0
      ambari-web/app/controllers/global/cluster_controller.js
  5. 6 1
      ambari-web/app/controllers/global/update_controller.js
  6. 107 0
      ambari-web/app/controllers/global/wizard_watcher_controller.js
  7. 5 0
      ambari-web/app/controllers/main/admin/highAvailability/nameNode/wizard_controller.js
  8. 5 0
      ambari-web/app/controllers/main/admin/highAvailability/rangerAdmin/wizard_controller.js
  9. 5 0
      ambari-web/app/controllers/main/admin/highAvailability/resourceManager/wizard_controller.js
  10. 5 0
      ambari-web/app/controllers/main/admin/kerberos/wizard_controller.js
  11. 5 0
      ambari-web/app/controllers/main/host/add_controller.js
  12. 5 0
      ambari-web/app/controllers/main/service/add_controller.js
  13. 5 0
      ambari-web/app/controllers/main/service/reassign_controller.js
  14. 3 1
      ambari-web/app/messages.js
  15. 20 18
      ambari-web/app/router.js
  16. 2 0
      ambari-web/app/routes/add_host_routes.js
  17. 2 0
      ambari-web/app/routes/add_kerberos_routes.js
  18. 2 0
      ambari-web/app/routes/add_service_routes.js
  19. 2 0
      ambari-web/app/routes/high_availability_routes.js
  20. 2 0
      ambari-web/app/routes/ra_high_availability_routes.js
  21. 2 0
      ambari-web/app/routes/reassign_master_routes.js
  22. 2 0
      ambari-web/app/routes/rm_high_availability_routes.js
  23. 6 1
      ambari-web/app/templates/application.hbs
  24. 10 4
      ambari-web/app/utils/helper.js
  25. 7 2
      ambari-web/app/views/main/menu.js
  26. 7 7
      ambari-web/test/app_test.js
  27. 13 13
      ambari-web/test/controllers/global/update_controller_test.js
  28. 151 0
      ambari-web/test/controllers/global/wizard_watcher_controller_test.js

+ 8 - 3
ambari-web/app/app.js

@@ -83,11 +83,12 @@ module.exports = Em.Application.create({
 
   /**
    * flag is true when upgrade process is running or aborted
+   * or wizard used by another user
    * @returns {boolean}
    */
-  upgradeIsNotFinished: function () {
-    return this.get('upgradeIsRunning') || this.get('upgradeAborted');
-  }.property('upgradeIsRunning', 'upgradeAborted'),
+  wizardIsNotFinished: function () {
+    return this.get('upgradeIsRunning') || this.get('upgradeAborted') || App.router.get('wizardWatcherController.isNonWizardUser');
+  }.property('upgradeIsRunning', 'upgradeAborted', 'router.wizardWatcherController.isNonWizardUser'),
 
   /**
    * compute user access rights by permission type
@@ -105,6 +106,10 @@ module.exports = Em.Application.create({
       return false;
     }
 
+    if (App.router.get('wizardWatcherController').get('isNonWizardUser')) {
+      return false;
+    }
+
     if (type.contains('upgrade_')) {
       //slice off "upgrade_" prefix to have actual permission type
       type = type.slice(8);

+ 1 - 0
ambari-web/app/assets/test/tests.js

@@ -47,6 +47,7 @@ var files = [
   'test/controllers/global/cluster_controller_test',
   'test/controllers/global/update_controller_test',
   'test/controllers/global/configuration_controller_test',
+  'test/controllers/global/wizard_watcher_controller_test',
   'test/controllers/main/alert_definitions_controller_test',
   'test/controllers/main/alerts/alert_definitions_actions_controller_test',
   'test/controllers/main/alerts/definitions_configs_controller_test',

+ 1 - 0
ambari-web/app/controllers.js

@@ -24,6 +24,7 @@ require('controllers/login_controller');
 require('controllers/wizard');
 require('controllers/installer');
 require('controllers/global/background_operations_controller');
+require('controllers/global/wizard_watcher_controller');
 require('controllers/main');
 require('controllers/main/dashboard');
 require('controllers/main/dashboard/config_history_controller');

+ 1 - 0
ambari-web/app/controllers/global/cluster_controller.js

@@ -206,6 +206,7 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, {
       self.restoreUpgradeState();
     }
 
+    App.router.get('wizardWatcherController').getUser();
 
     var updater = App.router.get('updateController');
 

+ 6 - 1
ambari-web/app/controllers/global/update_controller.js

@@ -154,6 +154,7 @@ App.UpdateController = Em.Controller.extend({
         App.updater.run(this, 'updateUnhealthyAlertInstances', 'updateAlertInstances', App.alertInstancesUpdateInterval, '\/main\/alerts.*');
       }
       App.updater.run(this, 'updateUpgradeState', 'isWorking', App.bgOperationsUpdateInterval);
+      App.updater.run(this, 'updateWizardWatcher', 'isWorking', App.bgOperationsUpdateInterval);
     }
   }.observes('isWorking', 'App.router.mainAlertInstancesController.isUpdating'),
 
@@ -570,11 +571,15 @@ App.UpdateController = Em.Controller.extend({
     var currentStateName = App.get('router.currentState.name'),
       parentStateName = App.get('router.parentState.name'),
       mainAdminStackAndUpgradeController = App.get('router.mainAdminStackAndUpgradeController');
-    if (!(currentStateName === 'versions' && parentStateName === 'stackAndUpgrade') && currentStateName !== 'stackUpgrade' && App.get('upgradeIsNotFinished') && !mainAdminStackAndUpgradeController.get('isLoadUpgradeDataPending')) {
+    if (!(currentStateName === 'versions' && parentStateName === 'stackAndUpgrade') && currentStateName !== 'stackUpgrade' && App.get('wizardIsNotFinished') && !mainAdminStackAndUpgradeController.get('isLoadUpgradeDataPending')) {
       mainAdminStackAndUpgradeController.loadUpgradeData(true).done(callback);
     } else {
       callback();
     }
+  },
+
+  updateWizardWatcher: function(callback) {
+    App.router.get('wizardWatcherController').getUser().complete(callback);
   }
 
 });

+ 107 - 0
ambari-web/app/controllers/global/wizard_watcher_controller.js

@@ -0,0 +1,107 @@
+/**
+ * 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');
+
+App.WizardWatcherController = Em.Controller.extend(App.UserPref, {
+  name: 'wizardWatcherController',
+
+  /**
+   * @const
+   */
+  PREF_KEY: 'wizard-data',
+
+  /**
+   * name of user who working with wizard
+   * @type {string|null}
+   */
+  wizardUser: null,
+
+  /**
+   * @type {string|null}
+   */
+  controllerName: null,
+
+  /**
+   * @type {Function}
+   */
+  mock: Em.K,
+
+  /**
+   * define whether Wizard is running
+   * @type {boolean}
+   */
+  isWizardRunning: function() {
+    return !Em.isNone(this.get('wizardUser'));
+  }.property('wizardUser'),
+
+  /**
+   * @type {string}
+   */
+  wizardDisplayName: function() {
+    if (this.get('controllerName')) {
+      return Em.I18n.t('wizard.inProgress').format(App.router.get(this.get('controllerName')).get('displayName'));
+    }
+    return "";
+  }.property('controllerName'),
+
+  /**
+   * define whether logged in user is the one who started wizard
+   * @type {boolean}
+   */
+  isNonWizardUser: function() {
+    return this.get('isWizardRunning') && this.get('wizardUser') !== App.router.get('loginName');
+  }.property('App.router.loginName', 'wizardUser').volatile(),
+
+  /**
+   * set user who launched wizard
+   * @returns {$.ajax}
+   */
+  setUser: function(controllerName) {
+    return this.postUserPref(this.get('PREF_KEY'), {
+      userName: App.router.get('loginName'),
+      controllerName: controllerName
+    });
+  },
+
+  /**
+   * reset user who launched wizard
+   * @returns {$.ajax}
+   */
+  resetUser: function() {
+    return this.postUserPref(this.get('PREF_KEY'), null);
+  },
+
+  /**
+   * get user who launched wizard
+   * @returns {$.ajax}
+   */
+  getUser: function() {
+    return this.getUserPref(this.get('PREF_KEY'));
+  },
+
+  getUserPrefSuccessCallback: function(data) {
+    if (Em.isNone(data)) {
+      this.set('wizardUser', null);
+      this.set('controllerName', null);
+    } else {
+      this.set('wizardUser', data.userName);
+      this.set('controllerName', data.controllerName);
+    }
+  }
+});

+ 5 - 0
ambari-web/app/controllers/main/admin/highAvailability/nameNode/wizard_controller.js

@@ -25,6 +25,11 @@ App.HighAvailabilityWizardController = App.WizardController.extend({
 
   totalSteps: 9,
 
+  /**
+   * @type {string}
+   */
+  displayName: Em.I18n.t('admin.highAvailability.wizard.header'),
+
   /**
    * Used for hiding back button in wizard
    */

+ 5 - 0
ambari-web/app/controllers/main/admin/highAvailability/rangerAdmin/wizard_controller.js

@@ -25,6 +25,11 @@ App.RAHighAvailabilityWizardController = App.WizardController.extend({
 
   totalSteps: 4,
 
+  /**
+   * @type {string}
+   */
+  displayName: Em.I18n.t('admin.ra_highAvailability.wizard.header'),
+
   isFinished: false,
 
   content: Em.Object.create({

+ 5 - 0
ambari-web/app/controllers/main/admin/highAvailability/resourceManager/wizard_controller.js

@@ -25,6 +25,11 @@ App.RMHighAvailabilityWizardController = App.WizardController.extend({
 
   totalSteps: 4,
 
+  /**
+   * @type {string}
+   */
+  displayName: Em.I18n.t('admin.rm_highAvailability.wizard.header'),
+
   isFinished: false,
 
   content: Em.Object.create({

+ 5 - 0
ambari-web/app/controllers/main/admin/kerberos/wizard_controller.js

@@ -28,6 +28,11 @@ App.KerberosWizardController = App.WizardController.extend({
 
   totalSteps: 8,
 
+  /**
+   * @type {string}
+   */
+  displayName: Em.I18n.t('admin.kerberos.wizard.header'),
+
   isKerberosWizard: true,
 
   stackConfigsLoaded: false,

+ 5 - 0
ambari-web/app/controllers/main/host/add_controller.js

@@ -25,6 +25,11 @@ App.AddHostController = App.WizardController.extend({
 
   totalSteps: 7,
 
+  /**
+   * @type {string}
+   */
+  displayName: Em.I18n.t('hosts.add.header'),
+
   /**
    * Used for hiding back button in wizard
    */

+ 5 - 0
ambari-web/app/controllers/main/service/add_controller.js

@@ -24,6 +24,11 @@ App.AddServiceController = App.WizardController.extend(App.AddSecurityConfigs, {
 
   totalSteps: 8,
 
+  /**
+   * @type {string}
+   */
+  displayName: Em.I18n.t('services.add.header'),
+
   /**
    * Used for hiding back button in wizard
    */

+ 5 - 0
ambari-web/app/controllers/main/service/reassign_controller.js

@@ -25,6 +25,11 @@ App.ReassignMasterController = App.WizardController.extend({
 
   totalSteps: 7,
 
+  /**
+   * @type {string}
+   */
+  displayName: Em.I18n.t('services.reassign.header'),
+
   /**
    * Used for hiding back button in wizard
    */

+ 3 - 1
ambari-web/app/messages.js

@@ -2706,5 +2706,7 @@ Em.I18n.translations = {
 
   'utils.ajax.errorMessage': 'Error message',
   'utils.ajax.defaultErrorPopupBody.message': 'received on {0} method for API: {1}',
-  'utils.ajax.defaultErrorPopupBody.statusCode': '{0} status code'
+  'utils.ajax.defaultErrorPopupBody.statusCode': '{0} status code',
+
+  'wizard.inProgress': '{0} in Progress'
 };

+ 20 - 18
ambari-web/app/router.js

@@ -399,26 +399,28 @@ App.Router = Em.Router.extend({
       }
     } else {
       if (this.get('clusterInstallCompleted')) {
-        App.clusterStatus.updateFromServer(false).complete(function () {
-          var route = 'main.dashboard.index';
-          var clusterStatusOnServer = App.clusterStatus.get('value');
-          if (clusterStatusOnServer) {
-            var wizardControllerRoutes = require('data/controller_route');
-            var wizardControllerRoute =  wizardControllerRoutes.findProperty('wizardControllerName', clusterStatusOnServer.wizardControllerName);
-            if (wizardControllerRoute) {
-              route =  wizardControllerRoute.route;
+        App.router.get('wizardWatcherController').getUser().complete(function() {
+          App.clusterStatus.updateFromServer(false).complete(function () {
+            var route = 'main.dashboard.index';
+            var clusterStatusOnServer = App.clusterStatus.get('value');
+            if (clusterStatusOnServer) {
+              var wizardControllerRoutes = require('data/controller_route');
+              var wizardControllerRoute =  wizardControllerRoutes.findProperty('wizardControllerName', clusterStatusOnServer.wizardControllerName);
+              if (wizardControllerRoute && !App.router.get('wizardWatcherController').get('isNonWizardUser')) {
+                route = wizardControllerRoute.route;
+              }
             }
-          }
-          if (wizardControllerRoute && wizardControllerRoute.wizardControllerName === 'mainAdminStackAndUpgradeController')  {
-            var clusterController =   App.router.get('clusterController');
-            clusterController.loadClusterName().done(function(){
-              clusterController.restoreUpgradeState().done(function(){
-                callback(route);
+            if (wizardControllerRoute && wizardControllerRoute.wizardControllerName === 'mainAdminStackAndUpgradeController')  {
+              var clusterController =   App.router.get('clusterController');
+              clusterController.loadClusterName().done(function(){
+                clusterController.restoreUpgradeState().done(function(){
+                  callback(route);
+                });
               });
-            });
-          } else {
-            callback(route);
-          }
+            } else {
+              callback(route);
+            }
+          });
         });
       } else {
         callback('installer');

+ 2 - 0
ambari-web/app/routes/add_host_routes.js

@@ -25,6 +25,7 @@ module.exports = App.WizardRoute.extend({
     var addHostController = router.get('addHostController');
     App.router.get('updateController').set('isWorking', true);
     addHostController.finish();
+    App.router.get('wizardWatcherController').resetUser();
     App.clusterStatus.setClusterStatus({
       clusterName: App.router.get('content.cluster.name'),
       clusterState: 'DEFAULT',
@@ -97,6 +98,7 @@ module.exports = App.WizardRoute.extend({
         }
       }
 
+      App.router.get('wizardWatcherController').setUser(addHostController.get('name'));
       router.transitionTo('step' + addHostController.get('currentStep'));
     });
 

+ 2 - 0
ambari-web/app/routes/add_kerberos_routes.js

@@ -78,6 +78,7 @@ module.exports = App.WizardRoute.extend({
             App.get('router').transitionTo('adminKerberos.index');
             location.reload();
           }
+          App.router.get('wizardWatcherController').resetUser();
           App.clusterStatus.setClusterStatus({
             clusterName: App.router.getClusterName(),
             clusterState: 'DEFAULT',
@@ -110,6 +111,7 @@ module.exports = App.WizardRoute.extend({
 
       }
       Em.run.next(function(){
+        App.router.get('wizardWatcherController').setUser(kerberosWizardController.get('name'));
         router.transitionTo('step' + kerberosWizardController.get('currentStep'));
       });
     });

+ 2 - 0
ambari-web/app/routes/add_service_routes.js

@@ -54,6 +54,7 @@ module.exports = App.WizardRoute.extend({
                 });
                 var exitPath = addServiceController.getDBProperty('onClosePath') || 'main.services.index';
                 addServiceController.finish();
+                App.router.get('wizardWatcherController').resetUser();
                 // We need to do recovery based on whether we are in Add Host or Installer wizard
                 App.clusterStatus.setClusterStatus({
                   clusterName: App.router.get('content.cluster.name'),
@@ -90,6 +91,7 @@ module.exports = App.WizardRoute.extend({
               }
             }
 
+            App.router.get('wizardWatcherController').setUser(addServiceController.get('name'));
             router.transitionTo('step' + addServiceController.get('currentStep'));
           });
         });

+ 2 - 0
ambari-web/app/routes/high_availability_routes.js

@@ -68,6 +68,7 @@ module.exports = App.WizardRoute.extend({
               controller.clearTasksData();
               controller.finish();
               App.router.get('updateController').set('isWorking', true);
+              App.router.get('wizardWatcherController').resetUser();
               App.clusterStatus.setClusterStatus({
                 clusterName: controller.get('content.cluster.name'),
                 clusterState: 'DEFAULT',
@@ -99,6 +100,7 @@ module.exports = App.WizardRoute.extend({
           }
         }
       Em.run.next(function () {
+        App.router.get('wizardWatcherController').setUser(highAvailabilityWizardController.get('name'));
         router.transitionTo('step' + highAvailabilityWizardController.get('currentStep'));
       });
     });

+ 2 - 0
ambari-web/app/routes/ra_high_availability_routes.js

@@ -63,6 +63,7 @@ module.exports = App.WizardRoute.extend({
           } else {
             router.get('updateController').set('isWorking', true);
             rAHighAvailabilityWizardController.finish();
+            App.router.get('wizardWatcherController').resetUser();
             App.clusterStatus.setClusterStatus({
               clusterName: App.router.getClusterName(),
               clusterState: 'DEFAULT',
@@ -93,6 +94,7 @@ module.exports = App.WizardRoute.extend({
             break;
         }
       }
+      App.router.get('wizardWatcherController').setUser(rAHighAvailabilityWizardController.get('name'));
       router.transitionTo('step' + rAHighAvailabilityWizardController.get('currentStep'));
     });
   },

+ 2 - 0
ambari-web/app/routes/reassign_master_routes.js

@@ -25,6 +25,7 @@ module.exports = App.WizardRoute.extend({
     var reassignMasterController = router.get('reassignMasterController');
     App.router.get('updateController').set('isWorking', true);
     reassignMasterController.finish();
+    App.router.get('wizardWatcherController').resetUser();
     App.clusterStatus.setClusterStatus({
       clusterName: App.router.get('content.cluster.name'),
       clusterState: 'DEFAULT',
@@ -102,6 +103,7 @@ module.exports = App.WizardRoute.extend({
                 break;
             }
           }
+          App.router.get('wizardWatcherController').setUser(reassignMasterController.get('name'));
           router.transitionTo('step' + currStep);
         });
       } else {

+ 2 - 0
ambari-web/app/routes/rm_high_availability_routes.js

@@ -61,6 +61,7 @@ module.exports = App.WizardRoute.extend({
           } else {
             router.get('updateController').set('isWorking', true);
             rMHighAvailabilityWizardController.finish();
+            App.router.get('wizardWatcherController').resetUser();
             App.clusterStatus.setClusterStatus({
               clusterName: App.router.getClusterName(),
               clusterState: 'DEFAULT',
@@ -92,6 +93,7 @@ module.exports = App.WizardRoute.extend({
         }
       }
       Em.run.next(function () {
+        App.router.get('wizardWatcherController').setUser(rMHighAvailabilityWizardController.get('name'));
         router.transitionTo('step' + rMHighAvailabilityWizardController.get('currentStep'));
       });
     });

+ 6 - 1
ambari-web/app/templates/application.hbs

@@ -99,13 +99,18 @@
   </div>
   <div class="container main-container">
     <div id="content">
-      {{#if App.upgradeIsNotFinished}}
+      {{#if App.wizardIsNotFinished}}
         <div class="ru-badge span12">
           <div class="navbar navbar-static-top clearfix">
             <div class="span11">
               {{#if isExistingClusterDataLoaded}}
                 <p class="span4 offset4">
                 <a class="brand cluster-name" href="#">
+                  {{#if App.router.wizardWatcherController.isNonWizardUser}}
+                      <span class="label upgrade-in-progress" {{action "mock" target="App.router.wizardWatcherController"}}>
+                        <i class="icon-cog"></i>&nbsp;{{App.router.wizardWatcherController.wizardDisplayName}}
+                      </span>
+                  {{/if}}
                   {{#if App.upgradeInProgress}}
                     {{#if App.router.mainAdminStackAndUpgradeController.isDowngrade}}
                       <span

+ 10 - 4
ambari-web/app/utils/helper.js

@@ -270,10 +270,16 @@ Em.Handlebars.registerHelper('highlight', function (property, words, fn) {
   return new Em.Handlebars.SafeString(property);
 });
 
-Em.Handlebars.registerHelper('isAccessible', function (context, options) {
-  if (App.isAccessible(context)) {
-    return options.fn(this);
-  }
+Em.Handlebars.registerHelper('isAccessible', function (property, options) {
+  var permission = Ember.Object.create({
+    isAccessible: function() {
+      return App.isAccessible(property);
+    }.property('App.router.wizardWatcherController.isWizardRunning')
+  });
+
+  // wipe out contexts so boundIf uses `this` (the permission) as the context
+  options.contexts = null;
+  return Ember.Handlebars.helpers.boundIf.call(permission, "isAccessible", options);
 });
 
 /**

+ 7 - 2
ambari-web/app/views/main/menu.js

@@ -49,8 +49,13 @@ App.MainMenuView = Em.CollectionView.extend({
       result.push({ label: Em.I18n.t('menu.item.views'), routing: 'views.index', isView: true, views: this.get('views').filterProperty('visible')});
     }
     return result;
-  }.property('App.router.loggedIn', 'views.length',
-    'App.router.clusterController.isLoaded', 'App.router.clusterInstallCompleted'),
+  }.property(
+    'App.router.loggedIn',
+    'views.length',
+    'App.router.clusterController.isLoaded',
+    'App.router.clusterInstallCompleted',
+    'App.router.wizardWatcherController.isWizardRunning'
+  ),
 
   itemViewClass: Em.View.extend({
 

+ 7 - 7
ambari-web/test/app_test.js

@@ -578,35 +578,35 @@ describe('App', function () {
 
   });
 
-  describe('#upgradeIsNotFinished', function () {
+  describe('#wizardIsNotFinished', function () {
 
     var cases = [
       {
         upgradeState: 'INIT',
-        upgradeIsNotFinished: false
+        wizardIsNotFinished: false
       },
       {
         upgradeState: 'IN_PROGRESS',
-        upgradeIsNotFinished: true
+        wizardIsNotFinished: true
       },
       {
         upgradeState: 'HOLDING',
-        upgradeIsNotFinished: true
+        wizardIsNotFinished: true
       },
       {
         upgradeState: 'HOLDING_TIMEDOUT',
-        upgradeIsNotFinished: true
+        wizardIsNotFinished: true
       },
       {
         upgradeState: 'ABORTED',
-        upgradeIsNotFinished: true
+        wizardIsNotFinished: true
       }
     ];
 
     cases.forEach(function (item) {
       it(item.upgradeState, function () {
         App.set('upgradeState', item.upgradeState);
-        expect(App.get('upgradeIsNotFinished')).to.equal(item.upgradeIsNotFinished);
+        expect(App.get('wizardIsNotFinished')).to.equal(item.wizardIsNotFinished);
       });
     });
 

+ 13 - 13
ambari-web/test/controllers/global/update_controller_test.js

@@ -62,7 +62,7 @@ describe('App.UpdateController', function () {
 
     it('isWorking = true', function () {
       controller.set('isWorking', true);
-      expect(App.updater.run.callCount).to.equal(11);
+      expect(App.updater.run.callCount).to.equal(12);
     });
   });
 
@@ -283,7 +283,7 @@ describe('App.UpdateController', function () {
         {
           currentStateName: 'versions',
           parentStateName: 'stackAndUpgrade',
-          upgradeIsNotFinished: true,
+          wizardIsNotFinished: true,
           isLoadUpgradeDataPending: true,
           loadUpgradeDataCallCount: 0,
           callbackCallCount: 1,
@@ -292,7 +292,7 @@ describe('App.UpdateController', function () {
         {
           currentStateName: 'stackUpgrade',
           parentStateName: null,
-          upgradeIsNotFinished: true,
+          wizardIsNotFinished: true,
           isLoadUpgradeDataPending: true,
           loadUpgradeDataCallCount: 0,
           callbackCallCount: 1,
@@ -301,7 +301,7 @@ describe('App.UpdateController', function () {
         {
           currentStateName: 'versions',
           parentStateName: null,
-          upgradeIsNotFinished: true,
+          wizardIsNotFinished: true,
           isLoadUpgradeDataPending: false,
           loadUpgradeDataCallCount: 1,
           callbackCallCount: 0,
@@ -310,7 +310,7 @@ describe('App.UpdateController', function () {
         {
           currentStateName: 'versions',
           parentStateName: null,
-          upgradeIsNotFinished: false,
+          wizardIsNotFinished: false,
           isLoadUpgradeDataPending: false,
           loadUpgradeDataCallCount: 0,
           callbackCallCount: 1,
@@ -319,7 +319,7 @@ describe('App.UpdateController', function () {
         {
           currentStateName: 'versions',
           parentStateName: null,
-          upgradeIsNotFinished: true,
+          wizardIsNotFinished: true,
           isLoadUpgradeDataPending: true,
           loadUpgradeDataCallCount: 0,
           callbackCallCount: 1,
@@ -328,7 +328,7 @@ describe('App.UpdateController', function () {
         {
           currentStateName: 'services',
           parentStateName: 'stackAndUpgrade',
-          upgradeIsNotFinished: true,
+          wizardIsNotFinished: true,
           isLoadUpgradeDataPending: false,
           loadUpgradeDataCallCount: 1,
           callbackCallCount: 0,
@@ -337,7 +337,7 @@ describe('App.UpdateController', function () {
         {
           currentStateName: 'services',
           parentStateName: 'stackAndUpgrade',
-          upgradeIsNotFinished: false,
+          wizardIsNotFinished: false,
           isLoadUpgradeDataPending: false,
           loadUpgradeDataCallCount: 0,
           callbackCallCount: 1,
@@ -346,7 +346,7 @@ describe('App.UpdateController', function () {
         {
           currentStateName: 'services',
           parentStateName: 'stackAndUpgrade',
-          upgradeIsNotFinished: true,
+          wizardIsNotFinished: true,
           isLoadUpgradeDataPending: true,
           loadUpgradeDataCallCount: 0,
           callbackCallCount: 1,
@@ -355,7 +355,7 @@ describe('App.UpdateController', function () {
         {
           currentStateName: 'widgets',
           parentStateName: 'dashboard',
-          upgradeIsNotFinished: true,
+          wizardIsNotFinished: true,
           isLoadUpgradeDataPending: false,
           loadUpgradeDataCallCount: 1,
           callbackCallCount: 0,
@@ -364,7 +364,7 @@ describe('App.UpdateController', function () {
         {
           currentStateName: 'widgets',
           parentStateName: 'dashboard',
-          upgradeIsNotFinished: false,
+          wizardIsNotFinished: false,
           isLoadUpgradeDataPending: false,
           loadUpgradeDataCallCount: 0,
           callbackCallCount: 1,
@@ -373,7 +373,7 @@ describe('App.UpdateController', function () {
         {
           currentStateName: 'widgets',
           parentStateName: 'dashboard',
-          upgradeIsNotFinished: true,
+          wizardIsNotFinished: true,
           isLoadUpgradeDataPending: true,
           loadUpgradeDataCallCount: 0,
           callbackCallCount: 1,
@@ -409,7 +409,7 @@ describe('App.UpdateController', function () {
         appGetMock.withArgs('router.mainAdminStackAndUpgradeController').returns(Em.Object.create({
           loadUpgradeData: mock.loadUpgradeData,
           isLoadUpgradeDataPending: item.isLoadUpgradeDataPending
-        })).withArgs('upgradeIsNotFinished').returns(item.upgradeIsNotFinished);
+        })).withArgs('wizardIsNotFinished').returns(item.wizardIsNotFinished);
         controller.updateUpgradeState(mock.callback);
         expect(mock.loadUpgradeData.callCount).to.equal(item.loadUpgradeDataCallCount);
         expect(mock.callback.callCount).to.equal(item.callbackCallCount);

+ 151 - 0
ambari-web/test/controllers/global/wizard_watcher_controller_test.js

@@ -0,0 +1,151 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+var App = require('app');
+require('controllers/global/wizard_watcher_controller');
+
+var controller;
+
+describe('App.wizardWatcherController', function () {
+  beforeEach(function() {
+    controller = App.WizardWatcherController.create();
+  });
+
+  describe("#isWizardRunning", function() {
+    it("wizardUser is null", function() {
+      controller.set('wizardUser', null);
+      controller.propertyDidChange('isWizardRunning');
+      expect(controller.get('isWizardRunning')).to.be.false;
+    });
+    it("wizardUser is correct", function() {
+      controller.set('wizardUser', 'admin');
+      controller.propertyDidChange('isWizardRunning');
+      expect(controller.get('isWizardRunning')).to.be.true;
+    });
+  });
+
+  describe("#wizardDisplayName", function() {
+    beforeEach(function () {
+      sinon.stub(App.router, 'get').returns(Em.Object.create({displayName: 'Wizard'}));
+    });
+    afterEach(function () {
+      App.router.get.restore();
+    });
+    it("controllerName is null", function() {
+      controller.set('controllerName', null);
+      controller.propertyDidChange('wizardDisplayName');
+      expect(controller.get('wizardDisplayName')).to.be.empty;
+    });
+    it("controllerName is correct", function() {
+      controller.set('controllerName', 'ctrl1');
+      controller.propertyDidChange('wizardDisplayName');
+      expect(controller.get('wizardDisplayName')).to.equal(Em.I18n.t('wizard.inProgress').format('Wizard'));
+    });
+  });
+
+
+  describe("#isNonWizardUser", function() {
+    beforeEach(function () {
+      sinon.stub(App.router, 'get').returns('admin');
+    });
+    afterEach(function () {
+      App.router.get.restore();
+    });
+    it("isWizardRunning is false", function() {
+      controller.reopen({
+        isWizardRunning: false
+      });
+      controller.propertyDidChange('isNonWizardUser');
+      expect(controller.get('isNonWizardUser')).to.be.false;
+    });
+    it("isWizardRunning is true, wizardUser is admin", function() {
+      controller.setProperties({
+        isWizardRunning: true,
+        wizardUser: 'admin'
+      });
+      controller.propertyDidChange('isNonWizardUser');
+      expect(controller.get('isNonWizardUser')).to.be.false;
+    });
+    it("isWizardRunning is true, wizardUser is admin2", function() {
+      controller.setProperties({
+        isWizardRunning: true,
+        wizardUser: 'admin2'
+      });
+      controller.propertyDidChange('isNonWizardUser');
+      expect(controller.get('isNonWizardUser')).to.be.true;
+    });
+  });
+
+  describe("#setUser()", function() {
+    beforeEach(function () {
+      sinon.stub(controller, 'postUserPref', Em.K);
+      sinon.stub(App.router, 'get').returns('admin');
+    });
+    afterEach(function () {
+      controller.postUserPref.restore();
+      App.router.get.restore();
+    });
+    it("post user pref", function() {
+      controller.setUser('ctrl1');
+      expect(controller.postUserPref.calledWith(controller.get('PREF_KEY'), {
+        userName: 'admin',
+        controllerName: 'ctrl1'
+      })).to.be.true;
+    });
+  });
+
+  describe("#resetUser()", function() {
+    beforeEach(function () {
+      sinon.stub(controller, 'postUserPref', Em.K);
+    });
+    afterEach(function () {
+      controller.postUserPref.restore();
+    });
+    it("post user pref", function() {
+      controller.resetUser('ctrl1');
+      expect(controller.postUserPref.calledWith(controller.get('PREF_KEY'), null)).to.be.true;
+    });
+  });
+
+  describe("#getUser()", function() {
+    beforeEach(function () {
+      sinon.stub(controller, 'getUserPref', Em.K);
+    });
+    afterEach(function () {
+      controller.getUserPref.restore();
+    });
+    it("get user pref", function() {
+      controller.getUser('ctrl1');
+      expect(controller.getUserPref.calledWith(controller.get('PREF_KEY'))).to.be.true;
+    });
+  });
+
+  describe("#getUserPrefSuccessCallback()", function() {
+    it("data is null", function() {
+      controller.getUserPrefSuccessCallback(null);
+      expect(controller.get('wizardUser')).to.be.null;
+      expect(controller.get('controllerName')).to.be.null;
+    });
+    it("data is correct", function() {
+      controller.getUserPrefSuccessCallback({userName: 'admin', controllerName: 'ctrl1'});
+      expect(controller.get('wizardUser')).to.equal('admin');
+      expect(controller.get('controllerName')).to.equal('ctrl1');
+    });
+  });
+});