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 <[email protected]> Authored: Fri Dec 19 15:52:47 2014 +0200 Committer: Andrii Tkach <[email protected]> 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
