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/12/19 19:30:24 UTC

ambari git commit: AMBARI-8819 Unit tests for dashboard views. (atkach)

Repository: ambari
Updated Branches:
  refs/heads/trunk a97576641 -> 3d37d5323


AMBARI-8819 Unit tests for dashboard views. (atkach)


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

Branch: refs/heads/trunk
Commit: 3d37d5323752075c4f57d387caa6cb3f77e6957f
Parents: a975766
Author: Andrii Tkach <at...@hortonworks.com>
Authored: Fri Dec 19 15:52:47 2014 +0200
Committer: Andrii Tkach <at...@hortonworks.com>
Committed: Fri Dec 19 20:28:50 2014 +0200

----------------------------------------------------------------------
 ambari-web/app/messages.js                      |   2 +
 .../views/main/dashboard/config_history_view.js |  25 +-
 ambari-web/app/views/main/dashboard/widget.js   | 280 ++++++++++-----
 ambari-web/app/views/main/dashboard/widgets.js  | 267 +++++++-------
 .../main/dashboard/config_history_view_test.js  | 215 ++++++++++-
 .../test/views/main/dashboard/widget_test.js    | 346 +++++++++++++++++-
 .../test/views/main/dashboard/widgets_test.js   | 354 +++++++++++++++++--
 7 files changed, 1215 insertions(+), 274 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/3d37d532/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index e341751..4ea3062 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -2223,6 +2223,8 @@ Em.I18n.translations = {
   'dashboard.widgets.NodeManagersLive': 'NodeManagers Live',
   'dashboard.widgets.YARNMemory': 'YARN Memory',
   'dashboard.widgets.YARNLinks': 'YARN Links',
+  'dashboard.widgets.error.invalid': 'Invalid! Enter a number between 0 - {0}',
+  'dashboard.widgets.error.smaller': 'Threshold 1 should be smaller than threshold 2!',
 
   'dashboard': {
     'widgets': {

http://git-wip-us.apache.org/repos/asf/ambari/blob/3d37d532/ambari-web/app/views/main/dashboard/config_history_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/config_history_view.js b/ambari-web/app/views/main/dashboard/config_history_view.js
index 354cae0..bb7f8ae 100644
--- a/ambari-web/app/views/main/dashboard/config_history_view.js
+++ b/ambari-web/app/views/main/dashboard/config_history_view.js
@@ -24,6 +24,11 @@ App.MainConfigHistoryView = App.TableView.extend(App.TableServerViewMixin, {
   templateName: require('templates/main/dashboard/config_history'),
 
   controllerBinding: 'App.router.mainConfigHistoryController',
+
+  /**
+   * @type {boolean}
+   * @default false
+   */
   filteringComplete: false,
   isInitialRendering: true,
 
@@ -172,7 +177,7 @@ App.MainConfigHistoryView = App.TableView.extend(App.TableServerViewMixin, {
     tagName: 'tr',
     showLessNotes: true,
     toggleShowLessStatus: function () {
-      this.set('showLessNotes', !this.get('showLessNotes'));
+      this.toggleProperty('showLessNotes');
     },
     didInsertElement: function () {
       App.tooltip(this.$("[rel='Tooltip']"));
@@ -185,12 +190,18 @@ App.MainConfigHistoryView = App.TableView.extend(App.TableServerViewMixin, {
   refresh: function () {
     var self = this;
     this.set('filteringComplete', false);
-    this.get('controller').load().done(function () {
-      self.set('isInitialRendering', false);
-      self.set('filteringComplete', true);
-      self.propertyDidChange('pageContent');
-      self.set('controller.resetStartIndex', false);
-    });
+    this.get('controller').load().done(this.refreshDone);
+  },
+
+  /**
+   * callback executed after refresh call done
+   * @method refreshDone
+   */
+  refreshDone: function () {
+    this.set('isInitialRendering', false);
+    this.set('filteringComplete', true);
+    this.propertyDidChange('pageContent');
+    this.set('controller.resetStartIndex', false);
   },
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/3d37d532/ambari-web/app/views/main/dashboard/widget.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widget.js b/ambari-web/app/views/main/dashboard/widget.js
index 95fc5fb..c7bcd7c 100644
--- a/ambari-web/app/views/main/dashboard/widget.js
+++ b/ambari-web/app/views/main/dashboard/widget.js
@@ -20,6 +20,10 @@ var App = require('app');
 
 App.DashboardWidgetView = Em.View.extend({
 
+  /**
+   * @type {string}
+   * @default null
+   */
   title: null,
   templateName: null, // each has specific template
 
@@ -27,120 +31,209 @@ App.DashboardWidgetView = Em.View.extend({
    * Setup model for widget by `model_type`. Usually `model_type` is a lowercase service name,
    * for example `hdfs`, `yarn`, etc. You need to set `model_type` in extended object View, for example
    * look App.DataNodeUpView.
-   * @return {Object} - model that set up in App.MainDashboardView.setWidgetsDataModel()
+   * @type {object} - model that set up in App.MainDashboardView.setWidgetsDataModel()
    */
   model : function () {
     if (!this.get('model_type')) return {};
     return this.get('parentView').get(this.get('model_type') + '_model');
-  }.property(), //data bind from parent view
+  }.property(),
+
+  /**
+   * id 1-10 used to identify
+   * @type {number}
+   * @default null
+   */
+  id: null,
 
-  id: null, // id 1-10 used to identify
-  viewID: function(){ // used by re-sort
+  /**
+   * html id bind to view-class: widget-(1)
+   * used by re-sort
+   * @type {string}
+   */
+  viewID: function () {
     return 'widget-' + this.get('id');
-  }.property('id'),  //html id bind to view-class: widget-(1)
+  }.property('id'),
   attributeBindings: ['viewID'],
 
+  /**
+   * @type {boolean}
+   */
   isPieChart: false,
+
+  /**
+   * @type {boolean}
+   */
   isText: false,
+
+  /**
+   * @type {boolean}
+   */
   isProgressBar: false,
+
+  /**
+   * @type {boolean}
+   */
   isLinks: false,
-  content: null, // widget content pieChart/ text/ progress bar/links/ metrics. etc
-  hiddenInfo: null, // more info details
+
+  /**
+   * widget content pieChart/ text/ progress bar/links/ metrics. etc
+   * @type {Array}
+   * @default null
+   */
+  content: null,
+
+  /**
+   * more info details
+   * @type {Array}
+   */
+  hiddenInfo: [],
+
+  /**
+   * @type {string}
+   */
   hiddenInfoClass: "hidden-info-two-line",
 
-  thresh1: null, //@type {Number}
-  thresh2: null, //@type {Number}
+  /**
+   * @type {number}
+   * @default null
+   */
+  thresh1: null,
+
+  /**
+   * @type {number}
+   * @default null
+   */
+  thresh2: null,
+
+  /**
+   * @type {Em.Object}
+   * @class
+   */
+  widgetConfig: Ember.Object.extend({
+    thresh1: '',
+    thresh2: '',
+    hintInfo: function () {
+      return Em.I18n.t('dashboard.widgets.hintInfo.common').format(this.get('maxValue'));
+    }.property('maxValue'),
+    isThresh1Error: false,
+    isThresh2Error: false,
+    errorMessage1: "",
+    errorMessage2: "",
+    maxValue: 0,
+    observeThresh1Value: function () {
+      var thresh1 = this.get('thresh1');
+      var thresh2 = this.get('thresh2');
+      var maxValue = this.get('maxValue');
+
+      if (thresh1.trim() != "") {
+        if (isNaN(thresh1) || thresh1 > maxValue || thresh1 < 0) {
+          this.set('isThresh1Error', true);
+          this.set('errorMessage1', Em.I18n.t('dashboard.widgets.error.invalid').format(maxValue));
+        } else if (this.get('isThresh2Error') === false && parseFloat(thresh2) <= parseFloat(thresh1)) {
+          this.set('isThresh1Error', true);
+          this.set('errorMessage1', Em.I18n.t('dashboard.widgets.error.smaller'));
+        } else {
+          this.set('isThresh1Error', false);
+          this.set('errorMessage1', '');
+        }
+      } else {
+        this.set('isThresh1Error', true);
+        this.set('errorMessage1', Em.I18n.t('admin.users.editError.requiredField'));
+      }
+      this.updateSlider();
+    }.observes('thresh1', 'maxValue'),
+    observeThresh2Value: function () {
+      var thresh2 = this.get('thresh2');
+      var maxValue = this.get('maxValue');
+
+      if (thresh2.trim() != "") {
+        if (isNaN(thresh2) || thresh2 > maxValue || thresh2 < 0) {
+          this.set('isThresh2Error', true);
+          this.set('errorMessage2', Em.I18n.t('dashboard.widgets.error.invalid').format(maxValue));
+        } else {
+          this.set('isThresh2Error', false);
+          this.set('errorMessage2', '');
+        }
+      } else {
+        this.set('isThresh2Error', true);
+        this.set('errorMessage2', Em.I18n.t('admin.users.editError.requiredField'));
+      }
+      this.updateSlider();
+    }.observes('thresh2', 'maxValue'),
+    updateSlider: function () {
+      var thresh1 = this.get('thresh1');
+      var thresh2 = this.get('thresh2');
+      // update the slider handles and color
+      if (this.get('isThresh1Error') === false && this.get('isThresh2Error') === false) {
+        $("#slider-range").slider('values', 0, parseFloat(thresh1));
+        $("#slider-range").slider('values', 1, parseFloat(thresh2));
+      }
+    }
+  }),
 
   didInsertElement: function () {
     App.tooltip(this.$("[rel='ZoomInTooltip']"), {placement : 'left'});
   },
 
+  /**
+   * delete widget
+   * @param {object} event
+   */
   deleteWidget: function (event) {
     var parent = this.get('parentView');
-    var self = this;
+
     if (App.get('testMode')) {
       //update view on dashboard
-      var objClass = parent.widgetsMapper(this.id);
+      var objClass = parent.widgetsMapper(this.get('id'));
       parent.get('visibleWidgets').removeObject(objClass);
       parent.get('hiddenWidgets').pushObject(Em.Object.create({displayName: this.get('title'), id: this.get('id'), checked: false}));
     } else {
       //reconstruct new persist value then post in persist
-      parent.getUserPref(parent.get('persistKey')).complete(function(){
-        var oldValue = parent.get('currentPrefObject');
-        var deletedId = self.get('id');
-        var newValue = Em.Object.create({
-          dashboardVersion: oldValue.dashboardVersion,
-          visible: [],
-          hidden: oldValue.hidden,
-          threshold: oldValue.threshold
-        });
-        for (var i = 0; i <= oldValue.visible.length - 1; i++) {
-          if (oldValue.visible[i] != deletedId) {
-            newValue.visible.push(oldValue.visible[i]);
-          }
-        }
-        newValue.hidden.push([deletedId, self.get('title')]);
-        parent.postUserPref(parent.get('persistKey'), newValue);
-        parent.translateToReal(newValue);
-      });
+      parent.getUserPref(parent.get('persistKey')).complete(this.deleteWidgetComplete);
     }
   },
 
-  editWidget: function (event) {
-    var self = this;
-    var max_tmp =  parseFloat(self.get('maxValue'));
-    var configObj = Ember.Object.create({
-      thresh1: self.get('thresh1') + '',
-      thresh2: self.get('thresh2') + '',
-      hintInfo: Em.I18n.t('dashboard.widgets.hintInfo.common').format(max_tmp),
-      isThresh1Error: false,
-      isThresh2Error: false,
-      errorMessage1: "",
-      errorMessage2: "",
-      maxValue: max_tmp,
-      observeNewThresholdValue: function () {
-        var thresh1 = this.get('thresh1');
-        var thresh2 = this.get('thresh2');
-        if (thresh1.trim() != "") {
-          if (isNaN(thresh1) || thresh1 > max_tmp || thresh1 < 0) {
-            this.set('isThresh1Error', true);
-            this.set('errorMessage1', 'Invalid! Enter a number between 0 - ' + max_tmp);
-          } else if (this.get('isThresh2Error') === false && parseFloat(thresh2)<= parseFloat(thresh1)) {
-            this.set('isThresh1Error', true);
-            this.set('errorMessage1', 'Threshold 1 should be smaller than threshold 2 !');
-          } else {
-            this.set('isThresh1Error', false);
-            this.set('errorMessage1', '');
-          }
-        } else {
-          this.set('isThresh1Error', true);
-          this.set('errorMessage1', 'This is required');
-        }
-
-        if (thresh2.trim() != "") {
-          if (isNaN(thresh2) || thresh2 > max_tmp || thresh2 < 0) {
-            this.set('isThresh2Error', true);
-            this.set('errorMessage2', 'Invalid! Enter a number between 0 - ' + max_tmp);
-          } else {
-            this.set('isThresh2Error', false);
-            this.set('errorMessage2', '');
-          }
-        } else {
-          this.set('isThresh2Error', true);
-          this.set('errorMessage2', 'This is required');
-        }
-
-        // update the slider handles and color
-        if (this.get('isThresh1Error') === false && this.get('isThresh2Error') === false) {
-          $("#slider-range").slider('values', 0 , parseFloat(thresh1));
-          $("#slider-range").slider('values', 1 , parseFloat(thresh2));
-        }
-      }.observes('thresh1', 'thresh2')
+  /**
+   * delete widget complete callback
+   */
+  deleteWidgetComplete: function () {
+    var parent = this.get('parentView');
+    var oldValue = parent.get('currentPrefObject');
+    var deletedId = this.get('id');
+    var newValue = Em.Object.create({
+      dashboardVersion: oldValue.dashboardVersion,
+      visible: oldValue.visible.slice(0).without(deletedId),
+      hidden: oldValue.hidden,
+      threshold: oldValue.threshold
+    });
+    newValue.hidden.push([deletedId, this.get('title')]);
+    parent.postUserPref(parent.get('persistKey'), newValue);
+    parent.translateToReal(newValue);
+  },
 
+  /**
+   * edit widget
+   * @param {object} event
+   */
+  editWidget: function (event) {
+    var configObj = this.get('widgetConfig').create({
+      thresh1: this.get('thresh1') + '',
+      thresh2: this.get('thresh2') + '',
+      maxValue: parseFloat(this.get('maxValue'))
     });
+    this.showEditDialog(configObj)
+  },
+
+  /**
+   *  show edit dialog
+   * @param {Em.Object} configObj
+   * @returns {App.ModalPopup}
+   */
+  showEditDialog: function (configObj) {
+    var self = this;
+    var maxValue = this.get('maxValue');
 
-    var browserVersion = this.getInternetExplorerVersion();
-    App.ModalPopup.show({
+    return App.ModalPopup.show({
       header: Em.I18n.t('dashboard.widgets.popupHeader'),
       classNames: [ 'sixty-percent-width-modal-edit-widget' ],
       bodyClass: Ember.View.extend({
@@ -148,11 +241,11 @@ App.DashboardWidgetView = Em.View.extend({
         configPropertyObj: configObj
       }),
       primary: Em.I18n.t('common.apply'),
-      onPrimary: function() {
+      onPrimary: function () {
         configObj.observeNewThresholdValue();
         if (!configObj.isThresh1Error && !configObj.isThresh2Error) {
-          self.set('thresh1', parseFloat(configObj.get('thresh1')) );
-          self.set('thresh2', parseFloat(configObj.get('thresh2')) );
+          self.set('thresh1', parseFloat(configObj.get('thresh1')));
+          self.set('thresh2', parseFloat(configObj.get('thresh2')));
 
           if (!App.get('testMode')) {
             // save to persist
@@ -169,6 +262,7 @@ App.DashboardWidgetView = Em.View.extend({
       },
 
       didInsertElement: function () {
+        var browserVersion = this.getInternetExplorerVersion();
         var handlers = [configObj.get('thresh1'), configObj.get('thresh2')];
         var colors = ['#95A800', '#FF8E00', '#B80000']; //color green, orange ,red
 
@@ -178,7 +272,7 @@ App.DashboardWidgetView = Em.View.extend({
           $("#slider-range").slider({
             range: true,
             min: 0,
-            max: max_tmp,
+            max: maxValue,
             values: handlers,
             create: function (event, ui) {
               updateColors(handlers);
@@ -196,8 +290,8 @@ App.DashboardWidgetView = Em.View.extend({
           function updateColors(handlers) {
             var colorstops = colors[0] + ", "; // start with the first color
             for (var i = 0; i < handlers.length; i++) {
-              colorstops += colors[i] + " " + handlers[i]*100/max_tmp + "%,";
-              colorstops += colors[i+1] + " " + handlers[i]*100/max_tmp + "%,";
+              colorstops += colors[i] + " " + handlers[i] * 100 / maxValue + "%,";
+              colorstops += colors[i + 1] + " " + handlers[i] * 100 / maxValue + "%,";
             }
             colorstops += colors[colors.length - 1];
             var sliderElement = $('#slider-range');
@@ -219,18 +313,21 @@ App.DashboardWidgetView = Em.View.extend({
     });
   },
 
-  getInternetExplorerVersion: function (){
+  /**
+   * @returns {number}
+   */
+  getInternetExplorerVersion: function () {
     var rv = -1; //return -1 for other browsers
     if (navigator.appName == 'Microsoft Internet Explorer') {
       var ua = navigator.userAgent;
-      var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
+      var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
       if (re.exec(ua) != null)
-        rv = parseFloat( RegExp.$1 ); // IE version 1-10
+        rv = parseFloat(RegExp.$1); // IE version 1-10
     }
     var isFirefox = typeof InstallTrigger !== 'undefined';   // Firefox 1.0+
     if (isFirefox) {
       return -2;
-    }else{
+    } else {
       return rv;
     }
   },
@@ -239,6 +336,7 @@ App.DashboardWidgetView = Em.View.extend({
    * for widgets has hidden info(hover info),
    * calculate the hover content top number
    * based on how long the hiddenInfo is
+   * @returns {string}
    */
   hoverContentTopClass: function () {
     var lineNum = this.get('hiddenInfo.length');

http://git-wip-us.apache.org/repos/asf/ambari/blob/3d37d532/ambari-web/app/views/main/dashboard/widgets.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets.js b/ambari-web/app/views/main/dashboard/widgets.js
index 107be63..74e05a5 100644
--- a/ambari-web/app/views/main/dashboard/widgets.js
+++ b/ambari-web/app/views/main/dashboard/widgets.js
@@ -23,13 +23,13 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
 
   name: 'mainDashboardWidgetsView',
 
-  templateName:require('templates/main/dashboard/widgets'),
+  templateName: require('templates/main/dashboard/widgets'),
 
-  didInsertElement:function () {
+  didInsertElement: function () {
     this.setWidgetsDataModel();
     this.setInitPrefObject();
     this.setOnLoadVisibleWidgets();
-    this.set('isDataLoaded',true);
+    this.set('isDataLoaded', true);
     Em.run.next(this, 'makeSortable');
   },
 
@@ -37,16 +37,16 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
    * List of services
    * @type {Ember.Enumerable}
    */
-  content:[],
+  content: [],
 
   /**
-   * @type {bool}
+   * @type {boolean}
    */
   isDataLoaded: false,
 
   /**
    * Define if some widget is currently moving
-   * @type {bool}
+   * @type {boolean}
    */
   isMoving: false,
 
@@ -55,7 +55,7 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
    */
   makeSortable: function () {
     var self = this;
-    $( "#sortable" ).sortable({
+    $("#sortable").sortable({
       items: "> div",
       //placeholder: "sortable-placeholder",
       cursor: "move",
@@ -85,10 +85,10 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
           });
         }
       },
-      activate: function(event, ui) {
+      activate: function (event, ui) {
         self.set('isMoving', true);
       },
-      deactivate: function(event, ui) {
+      deactivate: function (event, ui) {
         self.set('isMoving', false);
       }
     }).disableSelection();
@@ -98,31 +98,16 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
    * Set Service model values
    */
   setWidgetsDataModel: function () {
-    var services = App.Service.find();
-    var self = this;
-    if(App.get('services.hostMetrics').length > 0) {
-      self.set('host_metrics_model', App.get('services.hostMetrics'));
+    if (App.get('services.hostMetrics').length > 0) {
+      this.set('host_metrics_model', App.get('services.hostMetrics'));
     }
-    services.forEach(function (item) {
-      switch (item.get('serviceName')) {
-        case "HDFS":
-          self.set('hdfs_model',  App.HDFSService.find(item.get('id')) || item);
-          break;
-        case "YARN":
-          self.set('yarn_model', App.YARNService.find(item.get('id')) || item);
-          break;
-        case "MAPREDUCE":
-          self.set('mapreduce_model', App.MapReduceService.find(item.get('id')) || item);
-          break;
-        case "HBASE":
-          self.set('hbase_model', App.HBaseService.find(item.get('id')) || item);
-          break;
-        case "STORM":
-          self.set('storm_model', item);
-          break;
-        case "FLUME":
-          self.set('flume_model', item);
-          break;
+    App.Service.find().forEach(function (item) {
+      var extendedModel = App.Service.extendedModel[item.get('serviceName')];
+      var key = item.get('serviceName').toLowerCase() + '_model';
+      if (extendedModel && App[extendedModel].find(item.get('id'))) {
+        this.set(key, App[extendedModel].find(item.get('id')));
+      } else {
+        this.set(key, item);
       }
     }, this);
   },
@@ -130,7 +115,7 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
   /**
    * Load widget statuses to <code>initPrefObject</code>
    */
-  setInitPrefObject: function() {
+  setInitPrefObject: function () {
     //in case of some service not installed
     var visibleFull = [
       '2', '4', '8', '10',
@@ -138,54 +123,56 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
       '18', '1', '6', '5', '9',
       '3', '7', '15', '16', '20',
       '19', '21', '23',
-      '24', '25', '26', '27', '30',// all yarn
+      '24', '25', '26', '27', '30', // all yarn
       '28', // storm
       '29' // flume
     ]; // all in order
-    var hiddenFull = [['22','Region In Transition']];
+    var hiddenFull = [
+      ['22', 'Region In Transition']
+    ];
 
     // Display widgets for host metrics if the stack definition has a host metrics service to display it.
     if (this.get('host_metrics_model') == null) {
       var hostMetrics = ['11', '12', '13', '14'];
-      hostMetrics.forEach ( function (item) {
+      hostMetrics.forEach(function (item) {
         visibleFull = visibleFull.without(item);
       }, this);
     }
 
     if (this.get('hdfs_model') == null) {
-      var hdfs= ['1', '2', '3', '4', '5', '15', '17'];
-      hdfs.forEach ( function (item) {
+      var hdfs = ['1', '2', '3', '4', '5', '15', '17'];
+      hdfs.forEach(function (item) {
         visibleFull = visibleFull.without(item);
       }, this);
     }
     if (this.get('mapreduce_model') == null) {
       var map = ['6', '7', '8', '9', '10', '16', '18'];
-      map.forEach ( function (item) {
+      map.forEach(function (item) {
         visibleFull = visibleFull.without(item);
       }, this);
     }
     if (this.get('hbase_model') == null) {
       var hbase = ['19', '20', '21', '23'];
-      hbase.forEach ( function (item) {
+      hbase.forEach(function (item) {
         visibleFull = visibleFull.without(item);
       }, this);
       hiddenFull = [];
     }
     if (this.get('yarn_model') == null) {
       var yarn = ['24', '25', '26', '27', '30'];
-      yarn.forEach ( function (item) {
+      yarn.forEach(function (item) {
         visibleFull = visibleFull.without(item);
       }, this);
     }
     if (this.get('storm_model') == null) {
       var storm = ['28'];
-      storm.forEach(function(item) {
+      storm.forEach(function (item) {
         visibleFull = visibleFull.without(item);
       }, this);
     }
     if (this.get('flume_model') == null) {
       var flume = ['29'];
-      flume.forEach(function(item) {
+      flume.forEach(function (item) {
         visibleFull = visibleFull.without(item);
       }, this);
     }
@@ -225,57 +212,58 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
   /**
    * Submenu view for New Dashboard style
    * @type {Ember.View}
+   * @class
    */
   plusButtonFilterView: Ember.View.extend({
-      templateName: require('templates/main/dashboard/plus_button_filter'),
-      hiddenWidgetsBinding: 'parentView.hiddenWidgets',
-      visibleWidgetsBinding: 'parentView.visibleWidgets',
-      valueBinding: '',
-      widgetCheckbox: Em.Checkbox.extend({
-        didInsertElement: function() {
-          $('.checkbox').click(function(event) {
-            event.stopPropagation();
-          });
-        }
-      }),
-      closeFilter:function () {
-      },
-      applyFilter:function() {
-        this.closeFilter();
-        var parent = this.get('parentView');
-        var hiddenWidgets = this.get('hiddenWidgets');
-        var checkedWidgets = hiddenWidgets.filterProperty('checked', true);
-
-        if (App.get('testMode')) {
-          var visibleWidgets = this.get('visibleWidgets');
-          checkedWidgets.forEach(function(item){
-            var newObj = parent.widgetsMapper(item.id);
-            visibleWidgets.pushObject(newObj);
-            hiddenWidgets.removeObject(item);
-          }, this);
-        } else {
-          //save in persist
-          parent.getUserPref(parent.get('persistKey')).complete(function () {
-            var oldValue = parent.get('currentPrefObject') || parent.getDbProperty(parent.get('persistKey'));
-            var newValue = Em.Object.create({
-              dashboardVersion: oldValue.dashboardVersion,
-              visible: oldValue.visible,
-              hidden: [],
-              threshold: oldValue.threshold
-            });
-            checkedWidgets.forEach(function (item) {
-              newValue.visible.push(item.id);
-              hiddenWidgets.removeObject(item);
-            }, this);
-            hiddenWidgets.forEach(function (item) {
-              newValue.hidden.push([item.id, item.displayName]);
-            }, this);
-            parent.postUserPref(parent.get('persistKey'), newValue);
-            parent.setDBProperty(parent.get('persistKey'), newValue);
-            parent.translateToReal(newValue);
-          });
-        }
+    templateName: require('templates/main/dashboard/plus_button_filter'),
+    hiddenWidgetsBinding: 'parentView.hiddenWidgets',
+    visibleWidgetsBinding: 'parentView.visibleWidgets',
+    valueBinding: '',
+    widgetCheckbox: Em.Checkbox.extend({
+      didInsertElement: function () {
+        $('.checkbox').click(function (event) {
+          event.stopPropagation();
+        });
+      }
+    }),
+    closeFilter: Em.K,
+    applyFilter: function () {
+      var parent = this.get('parentView');
+      var hiddenWidgets = this.get('hiddenWidgets');
+      var checkedWidgets = hiddenWidgets.filterProperty('checked', true);
+
+      if (App.get('testMode')) {
+        var visibleWidgets = this.get('visibleWidgets');
+        checkedWidgets.forEach(function (item) {
+          var newObj = parent.widgetsMapper(item.id);
+          visibleWidgets.pushObject(newObj);
+          hiddenWidgets.removeObject(item);
+        }, this);
+      } else {
+        //save in persist
+        parent.getUserPref(parent.get('persistKey')).complete(this.applyFilterComplete);
       }
+    },
+    applyFilterComplete: function () {
+      var parent = this.get('parentView'),
+        hiddenWidgets = this.get('hiddenWidgets'),
+        oldValue = parent.get('currentPrefObject'),
+        newValue = Em.Object.create({
+          dashboardVersion: oldValue.dashboardVersion,
+          visible: oldValue.visible,
+          hidden: [],
+          threshold: oldValue.threshold
+        });
+      hiddenWidgets.filterProperty('checked').forEach(function (item) {
+        newValue.visible.push(item.id);
+        hiddenWidgets.removeObject(item);
+      }, this);
+      hiddenWidgets.forEach(function (item) {
+        newValue.hidden.push([item.id, item.displayName]);
+      }, this);
+      parent.postUserPref(parent.get('persistKey'), newValue);
+      parent.translateToReal(newValue);
+    }
   }),
 
   /**
@@ -287,15 +275,12 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
     var hidden = value.hidden;
     var threshold = value.threshold;
 
-    if (version == 'classic') {
-      this.set('isClassicDashboard', true);
-    } else if (version == 'new') {
-      this.set('isClassicDashboard', false);
+    if (version == 'new') {
       var visibleWidgets = [];
       var hiddenWidgets = [];
       // re-construct visibleWidgets and hiddenWidgets
-      for (var j = 0; j <= visible.length -1; j++) {
-        var id = visible[j];
+      for (var i = 0; i < visible.length; i++) {
+        var id = visible[i];
         var widgetClass = this.widgetsMapper(id);
         //override with new threshold
         if (threshold[id].length > 0) {
@@ -306,10 +291,9 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
         }
         visibleWidgets.pushObject(widgetClass);
       }
-      for (var j = 0; j <= hidden.length -1; j++) {
-        var id = hidden[j][0];
+      for (var j = 0; j < hidden.length; j++) {
         var title = hidden[j][1];
-        hiddenWidgets.pushObject(Em.Object.create({displayName:title , id: id, checked: false}));
+        hiddenWidgets.pushObject(Em.Object.create({displayName: title, id: hidden[j][0], checked: false}));
       }
       this.set('visibleWidgets', visibleWidgets);
       this.set('hiddenWidgets', hiddenWidgets);
@@ -320,29 +304,33 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
    * Set visibility-status for widgets
    */
   setOnLoadVisibleWidgets: function () {
-    var self = this;
     if (App.get('testMode')) {
       this.translateToReal(this.get('initPrefObject'));
     } else {
       // called when first load/refresh/jump back page
-      self.getUserPref(this.get('persistKey')).complete(function () {
-        var currentPrefObject = self.get('currentPrefObject') || self.getDBProperty(self.get('persistKey'));
-        if (currentPrefObject) { // fit for no dashboard version
-          if (!currentPrefObject.dashboardVersion) {
-            currentPrefObject.dashboardVersion = 'new';
-            self.postUserPref(self.get('persistKey'), currentPrefObject);
-            self.setDBProperty(self.get('persistKey'), currentPrefObject);
-          }
-          self.set('currentPrefObject', self.checkServicesChange(currentPrefObject));
-          self.translateToReal(self.get('currentPrefObject'));
-        }
-        else {
-          // post persist then translate init object
-          self.postUserPref(self.get('persistKey'), self.get('initPrefObject'));
-          self.setDBProperty(self.get('persistKey'), self.get('initPrefObject'));
-          self.translateToReal(self.get('initPrefObject'));
-        }
-      });
+      this.getUserPref(this.get('persistKey')).complete(this.setOnLoadVisibleWidgetsComplete);
+    }
+  },
+
+  /**
+   * complete load of visible widgets
+   */
+  setOnLoadVisibleWidgetsComplete: function () {
+    var currentPrefObject = this.get('currentPrefObject') || this.getDBProperty(this.get('persistKey'));
+    if (currentPrefObject) { // fit for no dashboard version
+      if (!currentPrefObject.dashboardVersion) {
+        currentPrefObject.dashboardVersion = 'new';
+        this.postUserPref(this.get('persistKey'), currentPrefObject);
+        this.setDBProperty(this.get('persistKey'), currentPrefObject);
+      }
+      this.set('currentPrefObject', this.checkServicesChange(currentPrefObject));
+      this.translateToReal(this.get('currentPrefObject'));
+    }
+    else {
+      // post persist then translate init object
+      this.postUserPref(this.get('persistKey'), this.get('initPrefObject'));
+      this.setDBProperty(this.get('persistKey'), this.get('initPrefObject'));
+      this.translateToReal(this.get('initPrefObject'));
     }
   },
 
@@ -354,7 +342,7 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
    */
   removeWidget: function (value, widget) {
     value.visible = value.visible.without(widget);
-    for (var j = 0; j <= value.hidden.length -1; j++) {
+    for (var j = 0; j < value.hidden.length; j++) {
       if (value.hidden[j][0] == widget) {
         value.hidden.splice(j, 1);
       }
@@ -369,9 +357,9 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
    * @returns {bool}
    */
   containsWidget: function (value, widget) {
-    var flag = value.visible.contains (widget);
-    for (var j = 0; j <= value.hidden.length -1; j++) {
-      if ( !flag && value.hidden[j][0] == widget) {
+    var flag = value.visible.contains(widget);
+    for (var j = 0; j < value.hidden.length; j++) {
+      if (!flag && value.hidden[j][0] == widget) {
         flag = true;
         break;
       }
@@ -393,7 +381,7 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
     // check each service, find out the newly added service and already deleted service
     if (this.get('hdfs_model') != null) {
       var hdfs = ['1', '2', '3', '4', '5', '15', '17'];
-      hdfs.forEach ( function (item) {
+      hdfs.forEach(function (item) {
         toDelete = self.removeWidget(toDelete, item);
       }, this);
     }
@@ -403,7 +391,7 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
       var hostMetrics = ['11', '12', '13', '14'];
       var flag = self.containsWidget(toDelete, hostMetrics[0]);
       if (flag) {
-        hostMetrics.forEach ( function (item) {
+        hostMetrics.forEach(function (item) {
           toDelete = self.removeWidget(toDelete, item);
         }, this);
       } else {
@@ -415,7 +403,7 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
       var map = ['6', '7', '8', '9', '10', '16', '18'];
       var flag = self.containsWidget(toDelete, map[0]);
       if (flag) {
-        map.forEach ( function (item) {
+        map.forEach(function (item) {
           toDelete = self.removeWidget(toDelete, item);
         }, this);
       } else {
@@ -426,7 +414,7 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
       var hbase = ['19', '20', '21', '22', '23'];
       var flag = self.containsWidget(toDelete, hbase[0]);
       if (flag) {
-        hbase.forEach ( function (item) {
+        hbase.forEach(function (item) {
           toDelete = self.removeWidget(toDelete, item);
         }, this);
       } else {
@@ -437,7 +425,7 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
       var yarn = ['24', '25', '26', '27', '30'];
       var flag = self.containsWidget(toDelete, yarn[0]);
       if (flag) {
-        yarn.forEach ( function (item) {
+        yarn.forEach(function (item) {
           toDelete = self.removeWidget(toDelete, item);
         }, this);
       } else {
@@ -448,7 +436,7 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
       var storm = ['28'];
       var flag = self.containsWidget(toDelete, storm[0]);
       if (flag) {
-        storm.forEach ( function (item) {
+        storm.forEach(function (item) {
           toDelete = self.removeWidget(toDelete, item);
         }, this);
       } else {
@@ -459,7 +447,7 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
       var flume = ['29'];
       var flag = self.containsWidget(toDelete, flume[0]);
       if (flag) {
-        flume.forEach ( function (item) {
+        flume.forEach(function (item) {
           toDelete = self.removeWidget(toDelete, item);
         }, this);
       } else {
@@ -468,10 +456,10 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
     }
     var value = currentPrefObject;
     if (toDelete.visible.length || toDelete.hidden.length) {
-      toDelete.visible.forEach ( function (item) {
+      toDelete.visible.forEach(function (item) {
         value = self.removeWidget(value, item);
       }, this);
-      toDelete.hidden.forEach ( function (item) {
+      toDelete.hidden.forEach(function (item) {
         value = self.removeWidget(value, item[0]);
       }, this);
     }
@@ -479,7 +467,7 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
       value.visible = value.visible.concat(toAdd);
       var allThreshold = this.get('initPrefObject').threshold;
       // add new threshold OR override with default value
-      toAdd.forEach ( function (item) {
+      toAdd.forEach(function (item) {
         value.threshold[item] = allThreshold[item];
       }, this);
     }
@@ -540,7 +528,7 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
     hidden: [],
     threshold: {1: [80, 90], 2: [85, 95], 3: [90, 95], 4: [80, 90], 5: [1000, 3000], 6: [70, 90], 7: [90, 95], 8: [50, 75], 9: [30000, 120000],
       10: [], 11: [], 12: [], 13: [], 14: [], 15: [], 16: [], 17: [], 18: [], 19: [], 20: [70, 90], 21: [10, 19.2], 22: [3, 10], 23: [],
-      24: [70, 90], 25: [], 26: [50, 75], 27: [50, 75], 28: [85, 95], 29: [85, 95], 30:[]} // id:[thresh1, thresh2]
+      24: [70, 90], 25: [], 26: [50, 75], 27: [50, 75], 28: [85, 95], 29: [85, 95], 30: []} // id:[thresh1, thresh2]
   }),
 
   /**
@@ -568,10 +556,10 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
   /**
    * Reset widgets visibility-status
    */
-  resetAllWidgets: function() {
+  resetAllWidgets: function () {
     var self = this;
-    App.showConfirmationPopup(function() {
-      if(!App.get('testMode')) {
+    App.showConfirmationPopup(function () {
+      if (!App.get('testMode')) {
         self.postUserPref(self.get('persistKey'), self.get('initPrefObject'));
         self.setDBProperty(self.get('persistKey'), self.get('initPrefObject'));
       }
@@ -586,8 +574,7 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
     return App.router.get('clusterController.gangliaUrl') + "/?r=hour&cs=&ce=&m=&s=by+name&c=HDPSlaves&tab=m&vn=";
   }.property('App.router.clusterController.gangliaUrl'),
 
-  showAlertsPopup: function (event) {
-  }
+  showAlertsPopup: Em.K
 
 });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3d37d532/ambari-web/test/views/main/dashboard/config_history_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/dashboard/config_history_view_test.js b/ambari-web/test/views/main/dashboard/config_history_view_test.js
index 379bba7..a4958b6 100644
--- a/ambari-web/test/views/main/dashboard/config_history_view_test.js
+++ b/ambari-web/test/views/main/dashboard/config_history_view_test.js
@@ -21,8 +21,12 @@ require('views/main/dashboard/config_history_view');
 
 describe('App.MainConfigHistoryView', function() {
   var view = App.MainConfigHistoryView.create({
+    totalCount: 0,
+    filteredCount: 0
+  });
+  view.reopen({
     controller: Em.Object.create({
-      name: 'mainConfigHistoryController',
+      name: 'mainConfigHistoryController11',
       paginationProps: [
         {
           name: 'displayLength'
@@ -34,12 +38,190 @@ describe('App.MainConfigHistoryView', function() {
       doPolling: Em.K,
       load: function () {
         return {done: Em.K};
-      }
-    }),
-    filteredCount: 0
+      },
+      colPropAssoc: []
+    })
   });
   view.removeObserver('controller.resetStartIndex', view, 'resetStartIndex');
 
+  describe("#filteredContentInfo", function () {
+    it("", function () {
+      view.set('filteredCount', 1);
+      view.set('totalCount', 2);
+      view.propertyDidChange('filteredContentInfo');
+      expect(view.get('filteredContentInfo')).to.eql(Em.I18n.t('tableView.filters.filteredConfigVersionInfo').format(1, 2));
+    });
+  });
+
+  describe("#serviceFilterView", function () {
+    var subView = view.get('serviceFilterView').create({
+      parentView: view
+    });
+
+    before(function () {
+      sinon.stub(App.Service, 'find').returns([Em.Object.create({
+        serviceName: 'S1',
+        displayName: 's1'
+      })])
+    });
+    after(function () {
+      App.Service.find.restore();
+    });
+    it("content", function () {
+      expect(subView.get('content')).to.eql([
+        {
+          "value": "",
+          "label": Em.I18n.t('common.all')
+        },
+        {
+          "value": "S1",
+          "label": "s1"
+        }
+      ]);
+    });
+
+    before(function () {
+      sinon.stub(view, 'updateFilter', Em.K);
+    });
+    after(function () {
+      view.updateFilter.restore();
+    });
+    it("call onChangeValue()", function () {
+      subView.set('column', 1);
+      subView.set('value', 'value');
+      subView.onChangeValue();
+      expect(view.updateFilter.calledWith(1, 'value', 'select')).to.be.true;
+    });
+  });
+
+  describe("#configGroupFilterView", function () {
+    var subView = view.get('configGroupFilterView').create({
+      parentView: view
+    });
+
+    before(function () {
+      sinon.stub(App.ServiceConfigVersion, 'find').returns([
+        Em.Object.create({groupName: 'G1'}),
+        Em.Object.create({groupName: 'G1'}),
+        Em.Object.create({groupName: null})
+      ]);
+    });
+    after(function () {
+      App.ServiceConfigVersion.find.restore();
+    });
+    it("content", function () {
+      expect(subView.get('content')).to.eql([
+        {
+          "value": "",
+          "label": Em.I18n.t('common.all')
+        },
+        {
+          "value": "G1",
+          "label": "G1"
+        }
+      ]);
+    });
+
+    before(function () {
+      sinon.stub(view, 'updateFilter', Em.K);
+    });
+    after(function () {
+      view.updateFilter.restore();
+    });
+    it("call onChangeValue()", function () {
+      subView.set('column', 1);
+      subView.set('value', 'value');
+      subView.onChangeValue();
+      expect(view.updateFilter.calledWith(1, 'value', 'select')).to.be.true;
+    });
+  });
+
+  describe("#modifiedFilterView", function () {
+    var subView = view.get('modifiedFilterView').create({
+      parentView: view,
+      controller: {
+        modifiedFilter: {
+          actualValues: {
+            startTime: 0,
+            endTime: 1
+          }
+        }
+      }
+    });
+
+    before(function () {
+      sinon.stub(view, 'updateFilter', Em.K);
+    });
+    after(function () {
+      view.updateFilter.restore();
+    });
+    it("call onTimeChange()", function () {
+      subView.set('column', 1);
+      subView.onTimeChange();
+      expect(view.updateFilter.calledWith(1, [0, 1], 'range')).to.be.true;
+    });
+  });
+
+  describe("#authorFilterView", function () {
+    var subView = view.get('authorFilterView').create({
+      parentView: view
+    });
+
+    before(function () {
+      sinon.stub(view, 'updateFilter', Em.K);
+    });
+    after(function () {
+      view.updateFilter.restore();
+    });
+    it("call onChangeValue()", function () {
+      subView.set('column', 1);
+      subView.set('value', 'value');
+      subView.onChangeValue();
+      expect(view.updateFilter.calledWith(1, 'value', 'string')).to.be.true;
+    });
+  });
+
+  describe("#notesFilterView", function () {
+    var subView = view.get('notesFilterView').create({
+      parentView: view
+    });
+
+    before(function () {
+      sinon.stub(view, 'updateFilter', Em.K);
+    });
+    after(function () {
+      view.updateFilter.restore();
+    });
+    it("call onChangeValue()", function () {
+      subView.set('column', 1);
+      subView.set('value', 'value');
+      subView.onChangeValue();
+      expect(view.updateFilter.calledWith(1, 'value', 'string')).to.be.true;
+    });
+  });
+
+  describe("#ConfigVersionView", function () {
+    var subView = view.get('ConfigVersionView').create({
+      parentView: view
+    });
+
+    before(function () {
+      sinon.stub(App, 'tooltip', Em.K);
+    });
+    after(function () {
+      App.tooltip.restore();
+    });
+    it("call didInsertElement()", function () {
+      subView.didInsertElement();
+      expect(App.tooltip.calledOnce).to.be.true;
+    });
+    it("call toggleShowLessStatus()", function () {
+      subView.set('showLessNotes', true);
+      subView.toggleShowLessStatus();
+      expect(subView.get('showLessNotes')).to.be.false;
+    });
+  });
+
   describe('#didInsertElement()', function() {
     it('', function() {
       sinon.stub(view, 'addObserver', Em.K);
@@ -90,6 +272,7 @@ describe('App.MainConfigHistoryView', function() {
       expect(view.get('controller.isPolling')).to.be.false;
     });
   });
+
   describe('#refresh()', function() {
     it('', function() {
       sinon.spy(view.get('controller'), 'load');
@@ -99,4 +282,28 @@ describe('App.MainConfigHistoryView', function() {
       view.get('controller').load.restore();
     });
   });
+
+  describe("#refreshDone()", function () {
+    before(function () {
+      sinon.stub(view, 'propertyDidChange', Em.K);
+    });
+    after(function () {
+      view.propertyDidChange.restore();
+    });
+    it("", function () {
+      view.set('filteringComplete', false);
+      view.set('controller.resetStartIndex', true);
+      view.refreshDone();
+      expect(view.get('filteringComplete')).to.be.true;
+      expect(view.get('controller.resetStartIndex')).to.be.false;
+    });
+  });
+
+  describe("#colPropAssoc", function () {
+    it("", function () {
+      view.set('controller.colPropAssoc', [1]);
+      view.propertyDidChange('colPropAssoc');
+      expect(view.get('colPropAssoc')).to.eql([1]);
+    });
+  });
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/3d37d532/ambari-web/test/views/main/dashboard/widget_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/dashboard/widget_test.js b/ambari-web/test/views/main/dashboard/widget_test.js
index 057b069..dab6b30 100644
--- a/ambari-web/test/views/main/dashboard/widget_test.js
+++ b/ambari-web/test/views/main/dashboard/widget_test.js
@@ -19,17 +19,166 @@
 var App = require('app');
 require('views/main/dashboard/widget');
 
-describe('App.DashboardWidgetView', function() {
-  var dashboardWidgetView = App.DashboardWidgetView.create();
+describe('App.DashboardWidgetView', function () {
+  var dashboardWidgetView = App.DashboardWidgetView.create({
+    parentView: Em.Object.create({
+      widgetsMapper: Em.K,
+      getUserPref: Em.K,
+      postUserPref: Em.K,
+      translateToReal: Em.K,
+      visibleWidgets: [],
+      hiddenWidgets: []
+    })
+  });
 
-  describe('#viewID', function() {
-    it('viewID is computed with id', function() {
+  describe('#viewID', function () {
+    it('viewID is computed with id', function () {
       dashboardWidgetView.set('id', 5);
       expect(dashboardWidgetView.get('viewID')).to.equal('widget-5');
     });
   });
 
-  describe('#hoverContentTopClass', function() {
+  describe('#model', function () {
+    it('model_type is null', function () {
+      dashboardWidgetView.set('model_type', null);
+      dashboardWidgetView.propertyDidChange('model');
+      expect(dashboardWidgetView.get('model')).to.eql({});
+    });
+    it('model_type is valid', function () {
+      dashboardWidgetView.set('model_type', 's');
+      dashboardWidgetView.propertyDidChange('model');
+      dashboardWidgetView.set('parentView.s_model', {'s': {}});
+      expect(dashboardWidgetView.get('model')).to.eql({'s': {}});
+    });
+  });
+
+  describe("#didInsertElement()", function () {
+    before(function () {
+      sinon.stub(App, 'tooltip', Em.K);
+    });
+    after(function () {
+      App.tooltip.restore();
+    });
+    it("call App.tooltip", function () {
+      dashboardWidgetView.didInsertElement();
+      expect(App.tooltip.calledOnce).to.be.true;
+    });
+  });
+
+  describe("#deleteWidget()", function () {
+    beforeEach(function () {
+      sinon.stub(dashboardWidgetView.get('parentView'), 'widgetsMapper').returns({});
+      sinon.stub(dashboardWidgetView.get('parentView'), 'getUserPref').returns({
+        complete: Em.K
+      });
+    });
+    afterEach(function () {
+      dashboardWidgetView.get('parentView').widgetsMapper.restore();
+      dashboardWidgetView.get('parentView').getUserPref.restore();
+    });
+    it("testMode is on", function () {
+      App.set('testMode', true);
+      dashboardWidgetView.set('id', '1');
+      dashboardWidgetView.deleteWidget();
+      expect(dashboardWidgetView.get('parentView').widgetsMapper.calledWith('1')).to.be.true;
+      expect(dashboardWidgetView.get('parentView.visibleWidgets')).to.be.empty;
+      expect(dashboardWidgetView.get('parentView.hiddenWidgets')).to.not.be.empty;
+    });
+    it("testMode is off", function () {
+      App.set('testMode', false);
+      dashboardWidgetView.set('parentView.persistKey', 'key');
+      dashboardWidgetView.deleteWidget();
+      expect(dashboardWidgetView.get('parentView').getUserPref.calledWith('key')).to.be.true;
+    });
+  });
+
+  describe("#deleteWidgetComplete()", function () {
+    before(function () {
+      sinon.spy(dashboardWidgetView.get('parentView'), 'postUserPref');
+      sinon.spy(dashboardWidgetView.get('parentView'), 'translateToReal');
+    });
+    after(function () {
+      dashboardWidgetView.get('parentView').postUserPref.restore();
+      dashboardWidgetView.get('parentView').translateToReal.restore();
+    });
+    it("", function () {
+      dashboardWidgetView.set('parentView.currentPrefObject', {
+        dashboardVersion: 'new',
+        visible: ['1', '2'],
+        hidden: [],
+        threshold: 'threshold'
+      });
+      dashboardWidgetView.set('parentView.persistKey', 'key');
+      dashboardWidgetView.deleteWidgetComplete();
+      expect(dashboardWidgetView.get('parentView').postUserPref.calledWith('key', {
+        dashboardVersion: 'new',
+        visible: ['2'],
+        hidden: ['1'],
+        threshold: 'threshold'
+      }));
+      expect(dashboardWidgetView.get('parentView').translateToReal.calledWith({
+        dashboardVersion: 'new',
+        visible: ['2'],
+        hidden: ['1'],
+        threshold: 'threshold'
+      }));
+    });
+  });
+
+  describe("#editWidget()", function () {
+    before(function () {
+      sinon.stub(dashboardWidgetView, 'showEditDialog', Em.K);
+    });
+    after(function () {
+      dashboardWidgetView.showEditDialog.restore();
+    });
+    it("call showEditDialog", function () {
+      dashboardWidgetView.editWidget();
+      expect(dashboardWidgetView.showEditDialog.calledOnce).to.be.true;
+    });
+  });
+
+  describe("#showEditDialog()", function () {
+    var obj = Em.Object.create({
+      observeNewThresholdValue: Em.K,
+      thresh1: '1',
+      thresh2: '2'
+    });
+    before(function () {
+      sinon.spy(obj, 'observeNewThresholdValue');
+      sinon.stub(dashboardWidgetView.get('parentView'), 'getUserPref').returns({
+        complete: Em.K
+      });
+    });
+    after(function () {
+      obj.observeNewThresholdValue.restore();
+      dashboardWidgetView.get('parentView').getUserPref.restore();
+    });
+    it("open popup", function () {
+      var popup = dashboardWidgetView.showEditDialog(obj);
+      popup.onPrimary();
+      expect(obj.observeNewThresholdValue.calledOnce).to.be.true;
+      expect(dashboardWidgetView.get('thresh1')).to.equal(1);
+      expect(dashboardWidgetView.get('thresh2')).to.equal(2);
+      expect(dashboardWidgetView.get('parentView').getUserPref.calledOnce).to.be.true;
+    });
+  });
+
+  describe('#model', function () {
+    it('model_type is null', function () {
+      dashboardWidgetView.set('model_type', null);
+      dashboardWidgetView.propertyDidChange('model');
+      expect(dashboardWidgetView.get('model')).to.eql({});
+    });
+    it('model_type is valid', function () {
+      dashboardWidgetView.set('model_type', 's');
+      dashboardWidgetView.propertyDidChange('model');
+      dashboardWidgetView.set('parentView.s_model', {'s': {}});
+      expect(dashboardWidgetView.get('model')).to.eql({'s': {}});
+    });
+  });
+
+  describe('#hoverContentTopClass', function () {
     var tests = [
       {
         h: ['', ''],
@@ -60,14 +209,195 @@ describe('App.DashboardWidgetView', function() {
         h: ['', '', '', ''],
         e: 'content-hidden-four-line',
         m: '4 lines'
+      },
+      {
+        h: ['', '', '', '', '', ''],
+        e: 'content-hidden-six-line',
+        m: '6 lines'
       }
     ];
-    tests.forEach(function(test) {
-      it(test.m, function() {
+    tests.forEach(function (test) {
+      it(test.m, function () {
         dashboardWidgetView.set('hiddenInfo', test.h);
         expect(dashboardWidgetView.get('hoverContentTopClass')).to.equal(test.e);
       });
     });
   });
 
-});
+  describe("#widgetConfig", function() {
+    var widget = dashboardWidgetView.get('widgetConfig').create();
+    describe("#hintInfo", function() {
+      it("", function() {
+        widget.set('maxValue', 1);
+        widget.propertyDidChange('hintInfo');
+        expect(widget.get('hintInfo')).to.equal(Em.I18n.t('dashboard.widgets.hintInfo.common').format(1));
+      });
+    });
+    describe("#observeThresh1Value", function() {
+      beforeEach(function () {
+        sinon.stub(widget, 'updateSlider', Em.K);
+      });
+      afterEach(function () {
+        widget.updateSlider.restore();
+      });
+      var testCases = [
+        {
+          data: {
+            thresh1: '',
+            maxValue: 0
+          },
+          result: {
+            isThresh1Error: true,
+            errorMessage1: Em.I18n.t('admin.users.editError.requiredField')
+          }
+        },
+        {
+          data: {
+            thresh1: 'NaN',
+            maxValue: 0
+          },
+          result: {
+            isThresh1Error: true,
+            errorMessage1: Em.I18n.t('dashboard.widgets.error.invalid').format(0)
+          }
+        },
+        {
+          data: {
+            thresh1: '-1',
+            maxValue: 0
+          },
+          result: {
+            isThresh1Error: true,
+            errorMessage1: Em.I18n.t('dashboard.widgets.error.invalid').format(0)
+          }
+        },
+        {
+          data: {
+            thresh1: '2',
+            maxValue: 1
+          },
+          result: {
+            isThresh1Error: true,
+            errorMessage1: Em.I18n.t('dashboard.widgets.error.invalid').format(1)
+          }
+        },
+        {
+          data: {
+            thresh1: '1',
+            thresh2: '1',
+            maxValue: 2
+          },
+          result: {
+            isThresh1Error: true,
+            errorMessage1: Em.I18n.t('dashboard.widgets.error.smaller')
+          }
+        },
+        {
+          data: {
+            thresh1: '1',
+            thresh2: '0',
+            maxValue: 2
+          },
+          result: {
+            isThresh1Error: true,
+            errorMessage1: Em.I18n.t('dashboard.widgets.error.smaller')
+          }
+        },
+        {
+          data: {
+            thresh1: '1',
+            thresh2: '2',
+            maxValue: 2
+          },
+          result: {
+            isThresh1Error: false,
+            errorMessage1: ''
+          }
+        }
+      ];
+      testCases.forEach(function (test) {
+        it("thresh1 - " + test.data.thresh1 + ', maxValue - ' + test.data.maxValue, function () {
+          widget.set('isThresh2Error', false);
+          widget.set('thresh2', test.data.thresh2 || "");
+          widget.set('thresh1', test.data.thresh1);
+          widget.set('maxValue', test.data.maxValue);
+          widget.observeThresh1Value();
+          expect(widget.get('isThresh1Error')).to.equal(test.result.isThresh1Error);
+          expect(widget.get('errorMessage1')).to.equal(test.result.errorMessage1);
+          expect(widget.updateSlider.called).to.be.true;
+        });
+      });
+    });
+
+    describe("#observeThresh2Value", function() {
+      beforeEach(function () {
+        sinon.stub(widget, 'updateSlider', Em.K);
+      });
+      afterEach(function () {
+        widget.updateSlider.restore();
+      });
+      var testCases = [
+        {
+          data: {
+            thresh2: '',
+            maxValue: 0
+          },
+          result: {
+            isThresh2Error: true,
+            errorMessage2: Em.I18n.t('admin.users.editError.requiredField')
+          }
+        },
+        {
+          data: {
+            thresh2: 'NaN',
+            maxValue: 0
+          },
+          result: {
+            isThresh2Error: true,
+            errorMessage2: Em.I18n.t('dashboard.widgets.error.invalid').format(0)
+          }
+        },
+        {
+          data: {
+            thresh2: '-1',
+            maxValue: 0
+          },
+          result: {
+            isThresh2Error: true,
+            errorMessage2: Em.I18n.t('dashboard.widgets.error.invalid').format(0)
+          }
+        },
+        {
+          data: {
+            thresh2: '2',
+            maxValue: 1
+          },
+          result: {
+            isThresh2Error: true,
+            errorMessage2: Em.I18n.t('dashboard.widgets.error.invalid').format(1)
+          }
+        },
+        {
+          data: {
+            thresh2: '2',
+            maxValue: 2
+          },
+          result: {
+            isThresh2Error: false,
+            errorMessage2: ''
+          }
+        }
+      ];
+      testCases.forEach(function (test) {
+        it("thresh2 - " + test.data.thresh2 + ', maxValue - ' + test.data.maxValue, function () {
+          widget.set('thresh2', test.data.thresh2 || "");
+          widget.set('maxValue', test.data.maxValue);
+          widget.observeThresh2Value();
+          expect(widget.get('isThresh2Error')).to.equal(test.result.isThresh2Error);
+          expect(widget.get('errorMessage2')).to.equal(test.result.errorMessage2);
+          expect(widget.updateSlider.called).to.be.true;
+        });
+      });
+    });
+  });
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/3d37d532/ambari-web/test/views/main/dashboard/widgets_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/dashboard/widgets_test.js b/ambari-web/test/views/main/dashboard/widgets_test.js
index 9ff1d40..8a2023c 100644
--- a/ambari-web/test/views/main/dashboard/widgets_test.js
+++ b/ambari-web/test/views/main/dashboard/widgets_test.js
@@ -23,15 +23,12 @@ var filters = require('views/common/filter_view');
 require('mixins/common/userPref');
 require('mixins/common/localStorage');
 require('views/main/dashboard/widgets');
-var mainDashboardWidgetsView;
 
-describe('App.MainDashboardWidgetsView', function() {
+describe('App.MainDashboardWidgetsView', function () {
 
-  beforeEach(function() {
-    mainDashboardWidgetsView = App.MainDashboardWidgetsView.create();
-  });
+  var view = App.MainDashboardWidgetsView.create();
 
-  describe('#setInitPrefObject', function() {
+  describe('#setInitPrefObject', function () {
     var host_metrics_widgets_count = 4;
     var hdfs_widgets_count = 7;
     var mapreduce_widgets_count = 7;
@@ -48,7 +45,7 @@ describe('App.MainDashboardWidgetsView', function() {
           yarn_model: null
         },
         e: {
-          visibleL: total_widgets_count - host_metrics_widgets_count- hdfs_widgets_count - mapreduce_widgets_count - hbase_widgets_count - yarn_widgets_count - 1,
+          visibleL: total_widgets_count - host_metrics_widgets_count - hdfs_widgets_count - mapreduce_widgets_count - hbase_widgets_count - yarn_widgets_count - 1,
           hiddenL: 0
         },
         m: 'All models are null'
@@ -76,7 +73,7 @@ describe('App.MainDashboardWidgetsView', function() {
           yarn_model: null
         },
         e: {
-          visibleL: total_widgets_count  - mapreduce_widgets_count - hbase_widgets_count - yarn_widgets_count - 1,
+          visibleL: total_widgets_count - mapreduce_widgets_count - hbase_widgets_count - yarn_widgets_count - 1,
           hiddenL: 0
         },
         m: 'mapreduce_model, hbase_model, yarn_model are null'
@@ -124,33 +121,342 @@ describe('App.MainDashboardWidgetsView', function() {
         m: 'All models are not null'
       }
     ]);
-    tests.forEach(function(test) {
-      it(test.m, function() {
-        mainDashboardWidgetsView.set('host_metrics_model', test.models.host_metrics_model);
-        mainDashboardWidgetsView.set('hdfs_model', test.models.hdfs_model);
-        mainDashboardWidgetsView.set('mapreduce_model', test.models.mapreduce_model);
-        mainDashboardWidgetsView.set('hbase_model', test.models.hbase_model);
-        mainDashboardWidgetsView.set('yarn_model', test.models.yarn_model);
-        mainDashboardWidgetsView.setInitPrefObject();
-        expect(mainDashboardWidgetsView.get('initPrefObject.visible.length')).to.equal(test.e.visibleL);
-        expect(mainDashboardWidgetsView.get('initPrefObject.hidden.length')).to.equal(test.e.hiddenL);
+    tests.forEach(function (test) {
+      it(test.m, function () {
+        view.set('host_metrics_model', test.models.host_metrics_model);
+        view.set('hdfs_model', test.models.hdfs_model);
+        view.set('mapreduce_model', test.models.mapreduce_model);
+        view.set('hbase_model', test.models.hbase_model);
+        view.set('yarn_model', test.models.yarn_model);
+        view.setInitPrefObject();
+        expect(view.get('initPrefObject.visible.length')).to.equal(test.e.visibleL);
+        expect(view.get('initPrefObject.hidden.length')).to.equal(test.e.hiddenL);
       });
     });
   });
 
-  describe('#persistKey', function() {
-    beforeEach(function() {
-      sinon.stub(App.router, 'get', function(k) {
+  describe('#persistKey', function () {
+    beforeEach(function () {
+      sinon.stub(App.router, 'get', function (k) {
         if ('loginName' === k) return 'tdk';
         return Em.get(App.router, k);
       });
     });
-    afterEach(function() {
+    afterEach(function () {
+      App.router.get.restore();
+    });
+    it('Check it', function () {
+      expect(view.get('persistKey')).to.equal('user-pref-tdk-dashboard');
+    });
+  });
+
+  describe("#didInsertElement()", function () {
+    before(function () {
+      sinon.stub(view, 'setWidgetsDataModel', Em.K);
+      sinon.stub(view, 'setInitPrefObject', Em.K);
+      sinon.stub(view, 'setOnLoadVisibleWidgets', Em.K);
+      sinon.stub(Em.run, 'next', Em.K);
+    });
+    after(function () {
+      view.setWidgetsDataModel.restore();
+      view.setInitPrefObject.restore();
+      view.setOnLoadVisibleWidgets.restore();
+      Em.run.next.restore();
+    });
+    it("", function () {
+      view.didInsertElement();
+      expect(view.setWidgetsDataModel.calledOnce).to.be.true;
+      expect(view.setInitPrefObject.calledOnce).to.be.true;
+      expect(view.setOnLoadVisibleWidgets.calledOnce).to.be.true;
+      expect(Em.run.next.calledWith(view, 'makeSortable')).to.be.true;
+      expect(view.get('isDataLoaded')).to.be.true
+    });
+  });
+
+  describe("#setWidgetsDataModel()", function () {
+    beforeEach(function () {
+      this.model = sinon.stub(App.Service, 'find');
+      this.get = sinon.stub(App, 'get');
+    });
+    afterEach(function () {
+      this.model.restore();
+      this.get.restore();
+    });
+    it("No host_metrics_model", function () {
+      this.get.returns([]);
+      this.model.returns([Em.Object.create({
+        serviceName: 'S1',
+        id: 'S1'
+      })]);
+      view.set('host_metrics_model', null);
+      view.setWidgetsDataModel();
+      expect(view.get('host_metrics_model')).to.be.null;
+      expect(view.get('s1_model')).to.eql(Em.Object.create({
+        serviceName: 'S1',
+        id: 'S1'
+      }));
+    });
+    it("host_metrics_model is present", function () {
+      this.get.returns([1]);
+      this.model.returns([Em.Object.create({
+        serviceName: 'HDFS',
+        id: 'HDFS'
+      })]);
+      view.set('host_metrics_model', null);
+      view.setWidgetsDataModel();
+      expect(view.get('host_metrics_model')).to.eql([1]);
+      expect(view.get('hdfs_model.id')).to.equal('HDFS');
+    });
+  });
+
+  describe("#plusButtonFilterView", function () {
+    var plusButtonFilterView = view.get('plusButtonFilterView').create({
+      parentView: view
+    });
+    plusButtonFilterView.reopen({
+      visibleWidgets: [],
+      hiddenWidgets: []
+    });
+
+    describe("#applyFilter()", function () {
+      var widget = {checked: true};
+      beforeEach(function () {
+        sinon.stub(view, 'getUserPref').returns({
+          complete: Em.K
+        });
+        sinon.stub(view, 'widgetsMapper').returns(widget);
+      });
+      afterEach(function () {
+        view.getUserPref.restore();
+        view.widgetsMapper.restore();
+      });
+      it("testMode is on", function () {
+        App.set('testMode', true);
+        plusButtonFilterView.set('hiddenWidgets', [widget]);
+        plusButtonFilterView.applyFilter();
+        expect(view.getUserPref.called).to.be.false;
+        expect(plusButtonFilterView.get('visibleWidgets')).not.to.be.empty;
+        expect(plusButtonFilterView.get('hiddenWidgets')).to.be.empty;
+      });
+      it("testMode is off", function () {
+        App.set('testMode', false);
+        plusButtonFilterView.applyFilter();
+        expect(view.getUserPref.calledOnce).to.be.true;
+      });
+    });
+
+    describe("#applyFilterComplete()", function () {
+      var widget = {checked: true};
+      beforeEach(function () {
+        sinon.stub(view, 'postUserPref');
+        sinon.stub(view, 'translateToReal');
+      });
+      afterEach(function () {
+        view.postUserPref.restore();
+        view.translateToReal.restore();
+      });
+      beforeEach(function () {
+        sinon.stub(App.router, 'get', function (k) {
+          if ('loginName' === k) return 'tdk';
+          return Em.get(App.router, k);
+        });
+      });
+      afterEach(function () {
+        App.router.get.restore();
+      });
+      it("", function () {
+        plusButtonFilterView.set('hiddenWidgets', [
+          Em.Object.create({
+            checked: true,
+            id: 1,
+            displayName: 'i1'
+          }),
+          Em.Object.create({
+            checked: false,
+            id: 2,
+            displayName: 'i2'
+          })
+        ]);
+        view.set('currentPrefObject', Em.Object.create({
+          dashboardVersion: 'new',
+          visible: [],
+          hidden: [],
+          threshold: 'threshold'
+        }));
+        view.set('persistKey', 'key');
+        plusButtonFilterView.applyFilterComplete();
+        expect(view.postUserPref.calledOnce).to.be.true;
+        expect(view.translateToReal.getCall(0).args[0]).to.eql(Em.Object.create({
+          dashboardVersion: 'new',
+          visible: [1],
+          hidden: [
+            [2, 'i2']
+          ],
+          threshold: 'threshold'
+        }));
+        expect(plusButtonFilterView.get('hiddenWidgets.length')).to.equal(1);
+      });
+    });
+  });
+
+  describe("#translateToReal()", function () {
+    beforeEach(function () {
+      sinon.stub(view, 'widgetsMapper').returns(Em.Object.create());
+      view.set('visibleWidgets', []);
+      view.set('hiddenWidgets', []);
+    });
+    afterEach(function () {
+      view.widgetsMapper.restore();
+    });
+    it("version is not new", function () {
+      var data = {
+        dashboardVersion: null,
+        visible: [],
+        hidden: [],
+        threshold: []
+      };
+      view.translateToReal(data);
+      expect(view.get('visibleWidgets')).to.be.empty;
+      expect(view.get('hiddenWidgets')).to.be.empty;
+    });
+    it("version is new", function () {
+      var data = {
+        dashboardVersion: 'new',
+        visible: [1],
+        hidden: [
+          ['id', 'title']
+        ],
+        threshold: [
+          [],
+          [
+            ['tresh1'],
+            ['tresh2']
+          ]
+        ]
+      };
+      view.translateToReal(data);
+      expect(view.get('visibleWidgets')).to.not.be.empty;
+      expect(view.get('hiddenWidgets')).to.not.be.empty;
+    });
+  });
+
+  describe("#setOnLoadVisibleWidgets()", function () {
+    beforeEach(function () {
+      sinon.stub(view, 'translateToReal', Em.K);
+      sinon.stub(view, 'getUserPref').returns({complete: Em.K});
+    });
+    afterEach(function () {
+      view.translateToReal.restore();
+      view.getUserPref.restore();
+    });
+
+    it("testMode is true", function () {
+      App.set('testMode', true);
+      view.setOnLoadVisibleWidgets();
+      expect(view.translateToReal.calledOnce).to.be.true;
+    });
+    it("testMode is false", function () {
+      App.set('testMode', false);
+      view.setOnLoadVisibleWidgets();
+      expect(view.getUserPref.calledOnce).to.be.true;
+    });
+  });
+
+  describe("#removeWidget()", function () {
+    it("", function () {
+      var widget = {};
+      var value = {
+        visible: [widget],
+        hidden: [
+          [widget]
+        ]
+      };
+      value = view.removeWidget(value, widget);
+      expect(value.visible).to.be.empty;
+      expect(value.hidden).to.be.empty;
+    });
+  });
+
+  describe("#containsWidget()", function () {
+    it("widget visible", function () {
+      var widget = {};
+      var value = {
+        visible: [widget],
+        hidden: [
+          [widget]
+        ]
+      };
+      expect(view.containsWidget(value, widget)).to.be.true;
+    });
+    it("widget absent", function () {
+      var widget = {};
+      var value = {
+        visible: [],
+        hidden: []
+      };
+      expect(view.containsWidget(value, widget)).to.be.false;
+    });
+    it("widget hidden", function () {
+      var widget = {};
+      var value = {
+        visible: [],
+        hidden: [
+          [widget]
+        ]
+      };
+      expect(view.containsWidget(value, widget)).to.be.true;
+    });
+  });
+
+  describe("#persistKey", function () {
+    before(function () {
+      sinon.stub(App.router, 'get').withArgs('loginName').returns('user');
+    });
+    after(function () {
       App.router.get.restore();
     });
-    it('Check it', function() {
-      expect(mainDashboardWidgetsView.get('persistKey')).to.equal('user-pref-tdk-dashboard');
+    it("", function () {
+      view.propertyDidChange('persistKey');
+      expect(view.get('persistKey')).to.equal('user-pref-user-dashboard');
     });
   });
 
+  describe("#getUserPrefSuccessCallback()", function () {
+    it("response is null", function () {
+      view.set('currentPrefObject', null);
+      view.getUserPrefSuccessCallback(null, {}, {});
+      expect(view.get('currentPrefObject')).to.be.null;
+    });
+    it("response is correct", function () {
+      view.set('currentPrefObject', null);
+      view.getUserPrefSuccessCallback({}, {}, {});
+      expect(view.get('currentPrefObject')).to.eql({});
+    });
+  });
+
+  describe("#resetAllWidgets()", function () {
+    before(function () {
+      sinon.stub(App, 'showConfirmationPopup', Em.K);
+    });
+    after(function () {
+      App.showConfirmationPopup.restore();
+    });
+    it("", function () {
+      view.resetAllWidgets();
+      expect(App.showConfirmationPopup.calledOnce).to.be.true;
+    });
+  });
+
+  describe("#gangliaUrl", function () {
+    before(function () {
+      sinon.stub(App.router, 'get').withArgs('clusterController.gangliaUrl').returns('url');
+    });
+    after(function () {
+      App.router.get.restore();
+    });
+    it("", function () {
+      view.propertyDidChange('gangliaUrl');
+      expect(view.get('gangliaUrl')).to.equal('url/?r=hour&cs=&ce=&m=&s=by+name&c=HDPSlaves&tab=m&vn=');
+    });
+  });
 });
\ No newline at end of file